JVM : VisualVM 排查内存泄漏的问题

1.美图

2.概述

3.内存泄漏demo

准备模拟内存泄漏demo

  1. 定义静态变量HashMap
  2. 分段循环创建对象,并加入HashMap
package com.java.book.jvm.chapter4;

import java.util.HashMap;
import java.util.Map;
public class CyclicDependencies {
    //声明缓存对象
    private static final Map map = new HashMap();
    
    public static void main(String args[]){
        try {
            //给打开visualvm时间
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //循环添加对象到缓存
        for(int i=0; i<1000000;i++){
            Person t = new Person();
            map.put("key"+i,t);
        }
        System.out.println("first");
        //为dump出堆提供时间
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0; i<1000000;i++){
            Person t = new Person();
            map.put("key"+i,t);
        }
        System.out.println("second");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0; i<3000000;i++){
            Person t = new Person();
            map.put("key"+i,t);
        }
        System.out.println("third");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for(int i=0; i<4000000;i++){
            Person t = new Person();
            map.put("key"+i,t);
        }
        System.out.println("forth");
        try {
            Thread.sleep(Integer.MAX_VALUE);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("qqqq");
    }
}

实体类

package com.java.book.jvm.chapter4;

import lombok.Data;

@Data
public class Person {
    private String name;
    private Integer age;
}

配置JVM参数:-Xms512m -Xmx512m -XX:-UseGCOverheadLimit -XX:MaxPermSize=50m

1.查看Visual GC标签,内容如下,这是输出first的截图
在这里插入图片描述
2.这是second 输出
在这里插入图片描述

3.这是输出forth的截图

在这里插入图片描述
通过2张图对比发现:
在这里插入图片描述
老生代一直在gc,当程序继续运行可以发现老生代gc还在继续:

在这里插入图片描述

增加到了7次,但是老生代的内存并没有减少。说明存在无法被回收的对象,可能是内存泄漏了。后面还会继续增加如下

在这里插入图片描述
而且程序卡死了
在这里插入图片描述

如何分析是那个对象泄漏了呢?打开抽样器标签:点击后如下图:

在这里插入图片描述
按照程序输出进行堆dump,当输出second时,dump一次,当输出forth时dump一次。
进入最后dump出来的堆标签,点击类:
在这里插入图片描述
结果如下
在这里插入图片描述
可以看出在两次间隔时间内Person对象实例一直在增加并且多了,说明该对象引用的方法可能存在内存泄漏。(这是为什么?)

如何查看对象引用关系呢?

右键选择类Person,选择“在实例视图中显示”,如下所示:
在这里插入图片描述
结果如下
在这里插入图片描述

左侧是创建的实例总数,右侧上部为该实例的结构,下面为引用说明,从图中可以看出在类CyclicDependencies里面被引用了,并且被HashMap引用。

如此可以确定泄漏的位置,进而根据实际情况进行分析解决。

因为在上面这个例子中,我们是一直往Map里加对象的,没有执行remove对象操作,也没有释放Map,所以通过visualVM可以看到堆占用的内存是很高的,当我执行remove对象操作或把map设为空时, 可以很直观的看到堆内存在GC时,一下子回收了很多对象

发布了1089 篇原创文章 · 获赞 451 · 访问量 136万+

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/104742177
今日推荐