JVM实战:内存溢出的定位与分析

2022-11-28 15:44:45 浏览数 (1)

文章目录

    • 模拟内存溢出
    • 运行测试
    • 导入到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字符串。

本文内容到此结束了, 如有收获欢迎点赞

0 人点赞