模拟OOM错误的产生
1、 编写代码
public class OOMError {
// 模拟OOM错误:
// 将JVM参数调小,方便模拟OOM错误 -Xms8m -Xmx8m -XX:+PrintGCDetails
public static void main(String[] args) {
String s = "qwertyuiopasdfghl";
while (true){
s += s + new Random().nextInt(888888888) + s + new Random().nextInt(888888888);
}
}
}
2、 修改JVM参数(调小,堆内存容易满)
3、运行查看错误及分析
OOM解决方案
1、尝试扩大内存,看结果,仍未解决,进入步骤2;
2、分析内存,看一下哪个地方出现了问题(专业工具:内存快照分析工具):
- 最快:使用内存快照分析工具(Eclipse使用MAT,Idea使用Jprofiler)
- 最慢:Debug,一行行分析代码
MAT,Jprofiler作用: - 分析Dump内存文件,快速定位内存泄漏;
- 获得堆中的数据
- 获得大的对象
1、安装Jprofiler插件:
2、下载jprofiler客户端
https://www.ej-technologies.com/download/jprofiler/version_92
3、配置ide
4、定位错误具体位置
- 测试代码:
package JVM.test;
import java.util.ArrayList;
/**
* TODO 测试OOM错误、JVM调优
* 将JVM参数调小,方便模拟OOM错误
* -Xms 设置初始化内存分配大小 1/64
* -Xmx 设置最大内存分配,默认 1/4
* 打印GC垃圾回收信息:-Xms8m -Xmx8m -XX:+PrintGCDetails
* OOM错误DUMP文件:-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError
*/
public class OOMError {
// 模拟OOM错误:
//
byte[] array = new byte[1*1024*1024]; // 1m
public static void main(String[] args) {
ArrayList<OOMError> list = new ArrayList<>();
int count = 0;
try {
while (true){
list.add(new OOMError()); // 通过Jprofiler发现问题所在行26
count = count +1;
}
}catch (Error e){
System.out.println("count:"+count);
e.printStackTrace();
}
}
}
-
运行结果:
出现错误,使用Exception并未捕获到异常,未输出执行次数,所以使用Error捕获
-
加配置信息,进行错误排查
-
错误信息已经dump下来,去项目根目录中查找该文件
-
打开该文件
注:找到问题以后,将项目中的java_pid1800.hprof.analysis文件夹删除,因为里面生成和很多文件。