JVM实战02(堆内存溢出)

2020/12/07 Jvm

JVM实战02(堆内存溢出)

目录

问题简介

堆内存溢出在实际项目上会是一个经常遇到的问题。如何定位?如何解决?

演示代码

1.配置JVM参数

-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

当发生堆内存溢出时转存内存快照。
在一些极端情况下,堆内存溢出可能直接导致线程崩溃。

2.模拟代码

public class OOMTest
{
    private static List<String> list = new ArrayList<>();

    public static void main(String[] args) {

        while (true)
        {
            list.add("test");
        }
    }
}

死循环往列表里添加元素,直到内存溢出。

使用MAT分析hprof文件

1.打开文件

Workbench-->File-->Open Heap Dump:
                        java_pid12532.hprof

打开文件后有一个初始化选项,直接关闭即可。                      

2.分析内存文件

1.从上图红色箭头1可以直接看出,Object对象占用了7M,其它占用很少,
这明显是不对。 

2.我们接着点击箭头2,Leak Suspects(泄漏疑点)

1.One instance of "java.lang.Object[]" loaded by "<system class loader>" 
occupies 7,292,936 (92.61%) bytes.
系统加载时object数组分配占用了2.61%

2.点击Details查看详细报告

1.红色箭头1,代表支配树积累的对象:
  。我们可以看到java.lang.Object[1823230]对象积累最多
  。左键点击java.lang.Object这一行-->List Objects-->
            .with outgoing references  //我引用了谁
            .with incoming references //谁引用了我,点击就可以
                                      查看最终哪一行代码导致的
            会发现是OOMTest这个类调用,我们可以查看类里的代码。

2.当然也可以点击红色箭头Thrad Details,查看线程详细信息。

我们也可以从这里线程调用栈查看到问题。

堆内存溢出场景

1.内存泄漏(如上步骤,使用Mat分析内存文件)
  找到这个泄漏的对象是通过怎样的路径,跟哪个对象关联,
  从而导致这个对象没有被回收掉。一般找到这个对象的创建
  位置,我们就能发现问题所在。

2.非内存泄漏
  。经过分析发现,目前内存对象必须都是存活的
    考虑调大机器内存,考虑对象生命周期是否太长。

Search

    Table of Contents