JVM的Heap Memory和Native Memory

JVM管理的内存能够整体划分为两部分:Heap Memory和Native Memory。前者咱们比较熟悉,是供Java应用程序使用的;后者也称为C-Heap,是供JVM自身进程使用的。Heap Memory及其内部各组成的大小能够经过JVM的一系列命令行参数来控制,在此不赘述。Native Memory没有相应的参数来控制大小,其大小依赖于操做系统进程的最大值(对于32位系统就是3~4G,各类系统的实现并不同),以及生成的Java字节码大小、建立的线程数量、维持java对象的状态信息大小(用于GC)以及一些第三方的包,好比JDBC驱动使用的native内存。html

Native Memory里存些什么?

  1. 管理java heap的状态数据(用于GC);
  2. JNI调用,也就是Native Stack;
  3. JIT(即便编译器)编译时使用Native Memory,而且JIT的输入(Java字节码)和输出(可执行代码)也都是保存在Native Memory;
  4. NIO direct buffer。对于IBM JVM和Hotspot,均可以经过-XX:MaxDirectMemorySize来设置nio直接缓冲区的最大值。默认是64M。超过这个时,会按照32M自动增大。
  5. 对于IBM的JVM某些版本实现,类加载器和类信息都是保存在Native Memory中的。

DirectBuffer的好处

DirectBuffer访问更快,避免了从HeapBuffer还须要从java堆拷贝到本地堆,操做系统直接访问的是DirectBuffer。DirectBuffer对象的数据实际是保存在native heap中,可是引用保存在HeapBuffer中。
另外,DirectBuffer的引用是直接分配在堆得Old区的,所以其回收时机是在FullGC时。所以,须要避免频繁的分配DirectBuffer,这样很容易致使Native Memory溢出。java

为何会内存溢出?

简单理解java process memory = java heap + native memory。所以内存溢出时,首先要区分是堆内存溢出仍是本地内存溢出。Native Memory本质上就是由于耗尽了进程地址空间。对于HotSpot JVM来书,不断的分配直接内存,会致使以下错误信息:Allocated 1953546760 bytes of native memory before running outlinux

参考资料:

http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html
http://www.techpaste.com/2012/07/steps-debugdiagnose-memory-memory-leaks-jvm/
https://sourcevirtues.wordpress.com/2013/01/14/java-heap-space-and-native-heap-problems/
http://www.theotherian.com/2013/08/understanding-javas-native-heap-or-c-heap.html
http://www.ibm.com/developerworks/library/l-kernel-memory-access/
http://www.ibm.com/developerworks/library/j-zerocopy/
http://en.wikipedia.org/wiki/Direct_memory_accessweb