本机直接内存–Direct Memory,不是JVM内存中的一部分,但是这部分内存也被频繁的使用,并且可能会产生OutOfMemoryError。
从JDK1.4中新加入了NIO类,引入了基于channel和Buffer的I/O方式,它可以使用Native函数库直接分配堆外内存,也就是在我们系统内存上分配了使用空间,然后使用了Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。为的是提高读写性能。
直接内存可以通过:-XX:MaxDirectMemorySize 来设置大小,如果不设置,默认和堆在最大值-Xmx一样大。
设置本机直接内存的原则就是,各种内存大小+本机直接内存大小<机器物理内存。
代码:
/**
* www.itzhimei.com
* 编程技术之美-IT之美
*/
public class DirectMemoryOOM {
private static final int SIZE_2MB = 1024*1024*2;
public static void main(String[] args) throws Exception {
Field uf = Unsafe.class.getDeclaredFields()[0];
uf.setAccessible(true);
Unsafe unsafe = (Unsafe)uf.get(null);
while(true) {
unsafe.allocateMemory(SIZE_2MB);
}
}
}
JVM参数:
-XX:MaxDirectMemorySize=10M
报错如下:
Exception in thread "main" java.lang.OutOfMemoryError
at sun.misc.Unsafe.allocateMemory(Native Method)
at com.itzhimei.study.jvm.DirectMemoryOOM.main(DirectMemoryOOM.java:19)
上面的代码可能很多人看不太懂,这一对unsafe是什么意思?怎么就产生直接内存溢出了?
Field uf = Unsafe.class.getDeclaredFields()[0];
uf.setAccessible(true);
Unsafe unsafe = (Unsafe)uf.get(null);
while(true) {
unsafe.allocateMemory(SIZE_2MB);
}
这就要我们大部分程序员并不会用到的Unsafe类。
因为要操作的是JVM之外的内存–直接内存,规范的操作是使用Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作,但是在NIO出现之前,操作直接内存,用的就是Unsafe类。
Unsafe类是什么?
Unsafe类使Java拥有了像C语言的指针一样操作内存空间的能力,同时也带来了指针的问题。过度的使用Unsafe类会使得出错的几率变大,因此Java官方并不建议使用的,官方文档也几乎没有。
知道了Unsafe的能力,所以上面的代码就实现直接内存的使用。也就最终导致直接内存溢出。
更多Unsafe请参考:https://blog.csdn.net/yjaspire/article/details/85248853
内容学习自周志明老师的《深入理解Java虚拟机》