由于内存不足,虚拟机没有可分配的内存了,垃圾回收器也不能释放更多的内存。程序抛出OutOfMemoryError.
一.模拟内存溢出
@RestController
public class CymController {
@GetMapping("/a")
public String index() {
List<byte[]> aalist = new ArrayList<>();
try {
while (true) {
byte[] bytes = new byte[1024];
aalist.add(bytes);
}
} catch (Error error) {
System.out.println("--------" +error);
}
return "11";
}
@GetMapping("/b")
public String b() {
return "Hello World b";
}
}
- 调用”/a”接口,打印 java.lang.OutOfMemoryError: Java heap space 错误,表示内存溢出。如果再”/b”接口,发现正常调用。是因为”aalist”是局部变量,抛出错误后,内存被回收了,程序也就恢复正常。
- 如果将 “List
aalist = new ArrayList<>()” 设置为成员变量。如果调用”/a”接口,则程序处于假死状态,再调用”/b”接口,一直处于等待。是因为”aalist”一直没发回收掉,程序一直在FullGC.
二.排查
- 主动导出Dump文件 jmap -dump:format=b,file=文件名
- 被动导出Dump文件 -XX:+HeapDumpOnOutOfMemoryError
- -XX:+HeapDumpOnOutOfMemoryError,从字面就可以很容易的理解,在发生OutOfMemoryError异常时,进行堆的Dump,这样就可以获取异常时的内存快照了。
-XX:HeapDumpPath=D:\heap-dump\ ,这个也很好理解,就是配置HeapDump的路径,方便我们管理,这里我们配置为D:\heap-dump,当然你也可以根据自己的需要,定义为其他的目录。
注意,HeapDumpPath的目录一定要手动创建好,如果没有这个目录,Dump会失败的。
通过MAT工具分析,哪些大对象可能存在问题,自己去分析。