模拟内存泄漏并MAT分析

记录一次如何通过MAT工具定位内存泄漏点

一、准备可以引起内存泄漏的代码OutOfMemoryGCLimitExceed.java 

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
 
public class OutOfMemoryGCLimitExceed {
    public static void addRandomDataToMap() {
        Map dataMap = new HashMap<>();
        Random r = new Random();
        while (true) {
            dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
        }
    }
    public static void main(String[] args) {
        OutOfMemoryGCLimitExceed.addRandomDataToMap();
    }
}

二、执行,并生成dump文件

 jmap -dump:format=b,file=heaptestout.bin 4824
生成dump文件heaptestout.bin
将heaptestout.bin从linux下载到本地

三、准备安装MAT工具

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

安装参考:https://www.jianshu.com/p/c6e2abb9f657

安装好如下界面:

模拟内存泄漏并MAT分析_第1张图片

四、MAT分析dump

  1. 名词解释
    Shallow Heap: 对象本身的大小。如果是数组或集合则是各个元素的总大小。
    Retained Heap: 对象本身的大小 + 引用的其他对象的大小。
    with incoming references:哪些对象引用了当前对象。
    with outgoing references:当前对象中引用了哪些对象。
  2. Leak Suspects

    模拟内存泄漏并MAT分析_第2张图片
    模拟内存泄漏并MAT分析_第3张图片
    可以看到,名字为main的进程“java.lang.Thread @ 0x86ba93f8 main”占用了99.8%的堆内存。OutOfMemoryGCLimitExceed.java文件的第11行,方法addRandomDataToMap可能存在问题。


    该进程自身大小为120B,但是引用的内存达902108176B,引用的对象为HashMap。

五、相关参考点说明

  1. jar -jar 配置堆内存的默认大小
    -Xms:用来设置程序初始化的时候内存栈的大小(相当于 -XX:MaxNewSize)。默认值为你当前机器最大内存的 1/64。
    -Xmx:用来设置你的应用程序(不是JVM)能够使用的最大内存数(相当于 -XX:MaxHeapSize)。默认值为你当前机器最大内存的 1/4。
    -Xmn:年轻代的大小。
    -Xss:每个线程stack的大小。
  2. 新生代、老年代、永久代

    模拟内存泄漏并MAT分析_第4张图片

    新生代:Young Generation,主要用来存放新生的对象,一般占据堆空间的1/3。在新生代中,保存着大量的刚刚创建的对象,但是大部分的对象都是朝生夕死,所以在新生代中会频繁的进行MinorGC,进行垃圾回收。新生代又细分为三个区:Eden区、SurvivorFrom、SurvivorTo区,三个区的默认比例为:8:1:1

    老年代:Old Generation,主要存放应用中生命周期长的内存对象。老年代比较稳定,不会频繁的进行MajorGC。而在MaiorGC之前才会先进行一次MinorGc,使得新生的对象进入老年代而导致空间不够才会触发。当无法找到足够大的连续空间分配给新创建的较大对象也会提前触发一次MajorGC进行垃圾回收腾出空间。

    永久代:Permanent Generation,永久代指的是永久保存区域。主要存放Class和Meta(元数据)的信息。
  3. 内存泄漏
    JVM发现内存不足,触发GC,发现对象一直被占用无法释放,会产生内存泄漏。

你可能感兴趣的:(内存泄漏,jvm,java)