学习内容:第2章 - Java 内存区域与内存溢出异常
实战代码均在我的 Git 仓库中:https://github.com/nx-xn2002/JVM-Learn.git
本机直接内存溢出
尝试直接通过反射获取 Unsafe
实例使用 Unsafe::.allocateMemory()
方法来申请分配内存(Unsafe
类的 getUnsafe()
方法指定只有引导类加载器才会返回实例,体现设计中希望只要虚拟机标准类库里面的类才能使用 Unsafe
的功能)
package com.nx.learn.jvm.oom;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* 本机直接内存溢出
* VM Options: -Xmx20M -XX:MaxDirectMemorySize=10M
*
* @author Ni Xiang
*/
public class DirectMemoryOOM {
private static final int _1MB = 1024 * 1024;
public static void main(String[] args) throws Exception {
Field unsafeField = Unsafe.class.getDeclaredFields()[0];
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
while (true) {
unsafe.allocateMemory(_1MB);
}
}
}
运行结果如下:
作者最后进行了延伸:要排查直接内存导致的内存溢出,首先可以看 Heap Dump 文件中是否有明显异常情况,直接内存导致的内存溢出的一个明显特征就是 Heap Dump 文件中没有明显异常情况。如果内存溢出后产生的 Dump 文件很小,程序中又间接使用了 DirectMemory
(常见场景:使用 NIO
),就可以重点考虑这方面的原因