本文来说下JVM性能优化之OOM问题
概述
在JVM内存区域中,除了程序计数器外,Java虚拟机的其他运行时区域都有可能发生OutOfMemoryError的异常,因为堆区域出现OOM的情况最常见,本文以堆上的内存出现OOM来详细分析下OOM的解决过程:
堆溢出
这种场景最为常见,报错信息:
java.lang.OutOfMemoryError: Java heap space
原因
- 代码中可能存在大对象分配
- 可能存在内存泄露,导致在多次GC之后,还是无法找到一块足够大的内存容纳当前对象。
解决方法
- 检查是否存在大对象的分配,最有可能的是大数组分配
- 通过jmap命令,把堆内存dump下来,使用mat工具分析一下,检查是否存在内存泄露的问题
- 如果没有找到明显的内存泄露,使用 -Xmx 加大堆内存
- 还有一点容易被忽略,检查是否有大量的自定义的 Finalizable 对象,也有可能是框架内部提供的,考虑其存在的必要性
堆溢出实践
在idea中设置JVM启动参数
设置JVM启动参数:-Xms20M设置堆的最小内存为20M,-Xmx20M设置堆的最大内存和最小内存一样,这样可以防止Java堆在内存不足时自动扩容。-XX:+HeapDumpOnOutOfMemoryError参数可以让虚拟机在出现内存溢出异常时Dump出内存堆运行时快照。-verbose:gc表示在控制台输出GC情况
HeapOOM.java
package cn.wideth.buz.utils;
import java.util.ArrayList;
import java.util.List;
public class HeapOOM {
public static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<>();
while (true) {
list.add(new OOMObject());
}
}
}
测试运行结果:
打开Java VisualVM
VisualVM是一个以监控、显示本地或者远程服务器 JVM工作情况,进行性能调优的工具。在jdk的bin目录下,如下图所示。
导出Heap内存运行时的dump文件
将dump文件装载进VisualVM,可以看到是在cn.wideth.buz.utils.HeapOOM类中的OOMObject对象个数实例过多,导致程序发生了OOM。
本文小结
本文介绍了堆区域出现OOM问题以及如何解决出现的OOM问题。