文章目录

  • 模拟内存溢出
  • 运行测试
  • 导入到MAT工具中进行分析



内存溢出在实际的生产环境中经常会遇到,比如,不断的将数据写入到一个集合中,出现了死循环,读取超大的文件等等,都可能会造成内存溢出。


如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。


首先,我们得先学会如何定位问题,然后再进行分析。如何定位问题呢,我们需要借助于jmap与MAT工具进行定位分析。


接下来,我们模拟内存溢出的场景。

模拟内存溢出

编写代码,向List集合中添加100万个字符串,每个字符串由1000个UUID组成。如果程序能够正常执行,最后打印ok。

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编辑器。

java内存异常定位 java内存溢出定位_开发语言

#参数如下
-Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

运行测试

测试结果如下:

E:\Java\jdk8u171\bin\java.exe -Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError 
"-javaagent:C:\idea\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=49839:C:\idea\IntelliJ IDEA 2019.3.2\bin" 
-Dfile.encoding=UTF-8 -classpath E:\Java\jdk8u171\jre\lib\charsets.jar;E:\Java\jdk8u171\jre\lib\deploy.jar;E:\Java\jdk8u171\jre\lib\ext\access-bridge-64.jar;E:\Java\jdk8u171\jre\lib\ext\cldrdata.jar;E:\Java\jdk8u171\jre\lib\ext\dnsns.jar;E:\Java\jdk8u171\jre\lib\ext\jaccess.jar;E:\Java\jdk8u171\jre\lib\ext\jfxrt.jar;E:\Java\jdk8u171\jre\lib\ext\localedata.jar;E:\Java\jdk8u171\jre\lib\ext\nashorn.jar;E:\Java\jdk8u171\jre\lib\ext\sunec.jar;E:\Java\jdk8u171\jre\lib\ext\sunjce_provider.jar;E:\Java\jdk8u171\jre\lib\ext\sunmscapi.jar;E:\Java\jdk8u171\jre\lib\ext\sunpkcs11.jar;E:\Java\jdk8u171\jre\lib\ext\zipfs.jar;E:\Java\jdk8u171\jre\lib\javaws.jar;E:\Java\jdk8u171\jre\lib\jce.jar;E:\Java\jdk8u171\jre\lib\jfr.jar;E:\Java\jdk8u171\jre\lib\jfxswt.jar;E:\Java\jdk8u171\jre\lib\jsse.jar;E:\Java\jdk8u171\jre\lib\management-agent.jar;E:\Java\jdk8u171\jre\lib\plugin.jar;E:\Java\jdk8u171\jre\lib\resources.jar;E:\Java\jdk8u171\jre\lib\rt.jar;E:\jvm-test\target\classes 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。

java内存异常定位 java内存溢出定位_开发语言_02

导入到MAT工具中进行分析

java内存异常定位 java内存溢出定位_java_03

可以看到,有88.22%的内存由Object[]数组占有,所以比较可疑

分析:这个可疑是正确的,因为已经有88%的内存都被它占有,这是非常有可能出现内存溢出的。

查看详情:

java内存异常定位 java内存溢出定位_开发语言_04


可以看到集合中存储了大量的uuid字符串。

本文内容到此结束了,
如有收获欢迎点赞👍收藏💖关注✔️,您的鼓励是我最大的动力。
如有错误❌疑问💬欢迎各位指出。
主页:共饮一杯无的博客汇总👨💻

保持热爱,奔赴下一场山海。🏃🏃🏃