侧边栏壁纸
博主头像
再见理想博主等级

只争朝夕,不负韶华

  • 累计撰写 112 篇文章
  • 累计创建 64 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

使用Eclipse Memory Analyzer进行内存泄漏分析

再见理想
2022-05-27 / 0 评论 / 0 点赞 / 683 阅读 / 769 字

一,代码模拟 OOM 异常

示例代码:

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

public class OomDemo {
    public static void main(String[] args) {
        List<User> list = new ArrayList<>();
        while (true) {
            User user = new User();
            user.setId(RandomUtil.randomLong(6));
            user.setName(RandomUtil.randomString(8));
            list.add(user);
        }
    }

    @Data
    public static class User {
        private Long id;
        private String name;
    }
}

修改 jvm 参数,发送 OOM 异常时设置自动保存 堆转储快照文件 快照:

-Xms: 初始堆大小。默认 (MaxHeapFreeRatio 参数可以调整) 空余堆内存小于 40%时,JVM就会增大堆直到 -Xmx 的最大限制。

-Xmx: 最大堆大小。默认 (MaxHeapFreeRatio 参数可以调整) 空余堆内存大于 70% 时,JVM会减少堆直到 -Xms 的最小限制。

-XX:+HeapDumpOnOutOfMemoryError:表示当 JVM 发生 OOM 时,自动生成 DUMP 文件 最重要的参数。

-XX:HeapDumpPath:(可选)表示生成 DUMP 文件的路径, 可以指定文件名称, -XX:HeapDumpPath=${目录}/java_heapdump.hprof。若不指定文件名,默认为:java_pid_date_time_heapDump.hprof

-XX:OnOutOfMemoryError:(可选)表示 OOM 时 需要触发的脚本,比如 重启动作,发送告警等等。

-Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:/

运行代码,生成 OOM 快照文件:

java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to d:/\java_pid12004.hprof ...
Heap dump file created [12383540 bytes in 0.061 secs]
Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.CommandLineWrapper.main(CommandLineWrapper.java:63)
Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded
	at com.ym.jvm.OomDemo.main(OomDemo.java:14)
	... 5 more

到快照输出路径查看堆转储快照文件,用 MAT 工具打开分析。MAT 工具下载

二,内存泄漏分析

2.1,导入堆转储快照文件,自动生成分析报告

加载完成后,会弹出分析报告:

点击详情可以看到更加详细的信息:

从分析报告中,我们可以看到内存占用过大的对象为 User 对象,被 ArrayList 数组引用,还能通过堆栈信息定位到具体的代码位置!

若分析报告查看不到有用信息,通过下面方法进行查询详细信息:

2.2,查看占用过大对象

可以通过 histogram 来进行查询,一般是按照占用的内存倒序进行排序的。

可以看到 OomDemo$User 对象占用非常大的堆空间。

2.3,查看对象被谁引用

可以通过 dominator_tree 分析对象的调用链。

展开 占用内存最多的线程查看,可以看到 User 对象被 ArrayList 引用,所在线程为主线程,所在类的位置为 OomDemo。

2.4,查看堆栈信息定位代码

可以通过 thread_overview 查看方法的调用链信息和堆栈信息。

展开占用内存过大的问题线程,可以看到问题代码位置。

0

评论区