文章目录
- 模拟内存溢出
- 运行测试
- 导入到MAT工具中进行分析
内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文件等等,都可能会造成内存溢出。 如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。 首先,我们得先学会如何定位问题,然后再进行分析。如何定位问题呢,我们需要借助于jmap与MAT工具进行定位分析。 接下来,我们模拟内存溢出的场景。
模拟内存溢出
编写代码,向List集合中添加100万个字符串,每个字符串由1000个UUID组成。如果程序能够正常执行,最后打印ok。
代码语言:javascript复制public class TestJvmOutOfMemory {
/**
* 实现,向集合中添加100万个字符串,每个字符串由100个UUID组成
*/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 1000000; i ) {
String str = "";
for (int j = 0; j < 1000; j ) {
str = UUID.randomUUID().toString();
}
list.add(str);
}
System.out.println("ok");
}
}
为了演示效果,我们将设置执行的参数,这里使用的是Idea编辑器。
代码语言:javascript复制#参数如下
-Xms8m -Xmx8m -XX: HeapDumpOnOutOfMemoryError
运行测试
测试结果如下:
代码语言:javascript复制E:Javajdk8u171binjava.exe -Xms8m -Xmx8m -XX: HeapDumpOnOutOfMemoryError
"-javaagent:C:ideaIntelliJ IDEA 2019.3.2libidea_rt.jar=49839:C:ideaIntelliJ IDEA 2019.3.2bin"
-Dfile.encoding=UTF-8 -classpath E:Javajdk8u171jrelibcharsets.jar;E:Javajdk8u171jrelibdeploy.jar;E:Javajdk8u171jrelibextaccess-bridge-64.jar;E:Javajdk8u171jrelibextcldrdata.jar;E:Javajdk8u171jrelibextdnsns.jar;E:Javajdk8u171jrelibextjaccess.jar;E:Javajdk8u171jrelibextjfxrt.jar;E:Javajdk8u171jrelibextlocaledata.jar;E:Javajdk8u171jrelibextnashorn.jar;E:Javajdk8u171jrelibextsunec.jar;E:Javajdk8u171jrelibextsunjce_provider.jar;E:Javajdk8u171jrelibextsunmscapi.jar;E:Javajdk8u171jrelibextsunpkcs11.jar;E:Javajdk8u171jrelibextzipfs.jar;E:Javajdk8u171jrelibjavaws.jar;E:Javajdk8u171jrelibjce.jar;E:Javajdk8u171jrelibjfr.jar;E:Javajdk8u171jrelibjfxswt.jar;E:Javajdk8u171jrelibjsse.jar;E:Javajdk8u171jrelibmanagement-agent.jar;E:Javajdk8u171jrelibplugin.jar;E:Javajdk8u171jrelibresources.jar;E:Javajdk8u171jrelibrt.jar;E:jvm-testtargetclasses cn.zjq.jvm.TestJvmOutOfMemory
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid30612.hprof ...
Heap dump file created [8290113 bytes in 0.030 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3332)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:124)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:448)
at java.lang.StringBuilder.append(StringBuilder.java:136)
at cn.zjq.jvm.TestJvmOutOfMemory.main(TestJvmOutOfMemory.java:17)
Process finished with exit code 1
可以看到,当发生内存溢出时,会dump文件到java_pid30612.hprof。
导入到MAT工具中进行分析
可以看到,有88.22%的内存由Object[]数组占有,所以比较可疑。 分析:这个可疑是正确的,因为已经有88%的内存都被它占有,这是非常有可能出现内存溢出的。 查看详情:
可以看到集合中存储了大量的uuid字符串。
本文内容到此结束了, 如有收获欢迎点赞