模拟排查堆OOM(内存溢出)
模拟OOM代码
public class HeapOverflowExample {
// 定义一个占用较大内存的类
static class LargeObject {
// 每个对象占用一个较大的内存块
// private byte[] data = new byte[1024 * 1024]; // 1 MB
}
public static void main(String[] args) {
// 创建一个列表来存储对象引用
List<LargeObject> objects = new ArrayList<>();
try {
while (true) {
// 创建新的 LargeObject 实例并添加到列表中
objects.add(new LargeObject());
// 打印当前对象数量
System.out.println("Number of objects: " + objects.size());
// 可以添加一些延迟来控制内存消耗速度
// Thread.sleep(100); // 注释掉,或根据需要调整
}
} catch (OutOfMemoryError e) {
System.err.println("OutOfMemoryError caught: " + e.getMessage());
e.printStackTrace();
}
}
}
通过设置JVM参数发生OOM时自动生成heapdump文件
heapdump(对存储)
- 包含了在特定时间点 JVM 堆内存中对象的详细信息,如:
- 对象的类型、数量。
- 对象之间的引用关系。
- 每个对象所占用的内存大小。
添加JVM参数
-Xms40m //堆初始内存
-Xmx40m //堆最大内存
-XX:+HeapDumpOnOutOfMemoryError //生成堆转储文件
-XX:HeapDumpPath=文件路径\文件名 //指定文件生成路径
运行代码
运行结果
打开jvisualvm
- 控制台命令(配置好环境变量之后)
jvisualvm
- 或者jdk bin目录下运行jvisualvm.exe
载入文件
查看具体是哪个对象造成了OOM
点击main可以查看具体信息
在类模块查看具体对象占用情况
通过命令查看堆使用情况
查看Java进程
Linux
- 方法一
ps -ef|grep java
- 方法二
jps -l (显示java进程的Id和软件名称)
jps -lmv(显示java进程的Id和软件名称;显示启动main输入参数;虚拟机参数)
Windows
jps
jps -l(显示java进程的Id和软件路径及名称)
使用jps -l
查看JVM内存分布情况
jmap -heap [PID]
查看存活的对象
jmap -histo:[设置只统计存活的对象] [PID]| [分页显示]
#示例
jmap -histo:live [PID]| more
运行时导出dump文件
jmap -dump:[指定文件格式],file=[文件路径] [pid]
# 示例
jmap -dump:format=b,file=D:\jvmdump.hprof 20076
可以通过jvisualvm加载dupm文件进行分析