ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

JVM监控及诊断工具之Eclipse MAT

2021-12-08 22:30:31  阅读:152  来源: 互联网

标签:MAT String 对象 Eclipse JVM 深堆 public 字节


1、简介

        MAT(Memory Analyzer Tool)工具是一款功能强大的Java堆内存分析器。可以用于查找内存泄露以及查看内存消耗情况。MAT是基于Eclipse开发的,不仅可以单独使用,还可以作为插件的形式嵌入在Eclipse中使用。是一款免费的性能分析工具,使用起来非常方便。

        MAT可以分析heap dump文件。在进行内存分析时,只要获得了反映当前设备内存映像的hprof文件,通过MAT打开就可以直观地看到当前的内存信息。一般来说,这些内存信息包含:

  • 所有的对象信息,包括对象实例、成员变量、存储于栈中的基本类型值和存储于堆中的其他对象的引用值。
  • 所有的类信息,包括classloader、类名称、父类、静态变量等
  • GCRoot到所有的这些对象的引用路径
  • 线程信息,包括线程的调用栈及此线程的线程局部变量。(TLS)

        MAT不是一个万能工具,它并不能处理所有类型的对存储文件。但是比较主流的厂家和格式。例如Sun,HP,SAP所采用的HPROF二进制堆存储文件,以及IBM的PHD堆存储文件等都能被很好的解析。

        最吸引人的还是能够快速为开发人员生成内存泄露报表,方便定位问题和分析问题。虽然MAT有如此强大的功能,但是内存分析也没有简单到一键完成的程度,很多内存问题还是需要我们从MAT展现给我们的信息当中通过经验和直觉来判断才能发现。

官方地址:https://www.eclipse.org/mat/downloads.php

 点击上面的exe文件:


2、获取dump文件方式

在这里插入图片描述

在这里插入图片描述

 2.1、下面我们先使用jmap生成dump文件

测试程序如下:

package com.kgf.kgfjavalearning2021.jvm.visualvm;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/***
 * -Xms600m -Xmx600m -XX:SurvivorRatio=8
 */
public class VisualVMTest {

    public static void main(String[] args) {

        List<Object> list = new ArrayList<>();
        while (true){
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            list.add(new Picture(new Random().nextInt(100*50)));
        }
    }
}

class Picture{

    private byte[] pixels;

    public Picture(int length) {
        this.pixels = new byte[length];
    }
}

在idea中添加vm环境变量:

 启动程序使用jmap命令:

 使用eclipse MAT打开:

 

2.2、分析堆dump文件

histogram:

        展示了各个类的实例数目以及这些实例的Shallow heap或 者Retained heap的总和

在这里插入图片描述

在这里插入图片描述

thread overview:查看系统中的Java线程 查看局部变量的信息 

在这里插入图片描述

在这里插入图片描述

 获得对象互相引用的关系:with outgoing references

在这里插入图片描述

在这里插入图片描述

with incoming references :

在这里插入图片描述

在这里插入图片描述  

3、浅堆与深堆

3.1、浅堆(shallow heap)

在这里插入图片描述

对象头代表根据类创建的对象的对象头,还有对象的大小不是可 能向8字节对齐,而是就向8字节对齐.

3.2、保留集(retained heap),也就是所谓的深堆

在这里插入图片描述

 注意: 当前深堆大小 = 当前对象的浅堆大小 + 对象中所包含对象的深堆大小

3.3、补充:对象实际大小

在这里插入图片描述 

4、练习

在这里插入图片描述 

在这里插入图片描述 

 在这里插入图片描述

5、案例分析:StudentTrace

 代码如下:

package com.kgf.kgfjavalearning2021.jvm.mat;

import java.util.ArrayList;
import java.util.List;

/**
 * 有一个学生浏览网页的记录程序,它将记录 每个学生访问过的网站地址。
 * 它由三个部分组成:Student、WebPage和StudentTrace三个类
 *
 *  -XX:+HeapDumpBeforeFullGC -XX:HeapDumpPath=F:\mat_log\student.hprof
 * 
 */
public class StudentTrace {
    static List<WebPage> webpages = new ArrayList<WebPage>();

    public static void createWebPages() {
        for (int i = 0; i < 100; i++) {
            WebPage wp = new WebPage();
            wp.setUrl("http://www." + Integer.toString(i) + ".com");
            wp.setContent(Integer.toString(i));
            webpages.add(wp);
        }
    }

    public static void main(String[] args) {
        createWebPages();//创建了100个网页
        //创建3个学生对象
        Student st3 = new Student(3, "Tom");
        Student st5 = new Student(5, "Jerry");
        Student st7 = new Student(7, "Lily");

        for (int i = 0; i < webpages.size(); i++) {
            if (i % st3.getId() == 0)
                st3.visit(webpages.get(i));
            if (i % st5.getId() == 0)
                st5.visit(webpages.get(i));
            if (i % st7.getId() == 0)
                st7.visit(webpages.get(i));
        }
        webpages.clear();
        System.gc();
    }
}

class Student {
    private int id;
    private String name;
    private List<WebPage> history = new ArrayList<>();

    public Student(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<WebPage> getHistory() {
        return history;
    }

    public void setHistory(List<WebPage> history) {
        this.history = history;
    }

    public void visit(WebPage wp) {
        if (wp != null) {
            history.add(wp);
        }
    }
}


class WebPage {
    private String url;
    private String content;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

在idea中配置环境变量:

启动程序生成dump文件,使用MAT打开:

在这里插入图片描述 结论:
        elementData数组的浅堆是80个字节,而elementData数组中的所有WebPage对象的深堆之和是1208个字节,所以加在一起就是elementData数组的深堆之和,也就是1288个字节
解释:
        我说“elementData数组的浅堆是80个字节”,其中15个对象一共是60个字节,对象头8个字节,数组对象本身4个字节,这些的和是72个字节,然后总和要是8的倍数,“elementData数组的浅堆是80个字节”我说“WebPage对象的深堆之和是1208个字节”,一共有15个对象,
其中0、21、42、63、84、35、70不仅仅是7的倍数,还是3或者5的倍数,所以这几个数值对应的i不能计算在深堆之内,这15个对象中大多数的深堆是152个字节,但是i是0和7的那两个深堆是144个字节,所以(13*152+144*2)-(6*152+144)=1208,所以这也印证了我上面的话,即“WebPage对象的深堆之和是1208个字节”因此“elementData数组的浅堆80个字节”加上“WebPage对象的深堆之和1208个字节”,正好是1288个字节,说明“elementData数组的浅堆1288个字节”

标签:MAT,String,对象,Eclipse,JVM,深堆,public,字节
来源: https://blog.csdn.net/K_520_W/article/details/121736542

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有