Featured image of post 实战复盘:如何用JProfiler在30分钟内解决内存泄漏?

实战复盘:如何用JProfiler在30分钟内解决内存泄漏?

通过JProfiler分析Dump文件,开发者可以快速定位内存泄漏或大对象问题。生成准确的快照:确保JVM参数配置正确。掌握分析工具的核心功能:如引用链追踪、大对象筛选。结合代码与业务场景:避免“治标不治本”的临时修复。

问题

近日公司有服务内存泄露导致服务假死,导致服务不可用。第一时间查看异常日志,并未发现什么异常,但是进入pod发现生成java_pid1.hprof文件。平台的线上环境均配置了jvm参数,在发生OOM时会自动dump出堆转储文件,接下来就要从dump文件入手来定位问题了。

项目背景

在Java应用开发中,内存溢出(Out Of Memory, OOM)是开发者最常遇到的严重问题之一。OOM通常由以下原因引发:

  • 内存分配不足:JVM堆内存设置过小,无法应对高并发或复杂业务场景。
  • 代码漏洞:如内存泄漏(对象无法被GC回收)、大对象未释放、集合类滥用等。
  • 系统突然的流量增大,原有的可用内存不足以支撑等。

当系统突发OOM时,若仅依赖日志定位问题,往往难以快速找到根源。此时,JProfiler作为一款强大的JVM性能分析工具,能够通过内存快照(Dump文件)精准定位问题代码,成为解决问题的关键。

环境

官方网址:https://www.ej-technologies.com/jprofiler/download92

  1. JDK版本:Java 8+(推荐JDK 11及以上,支持更全面的诊断功能)。
  2. JProfiler版本:12.0+(支持与IDEA插件集成)。
  3. IDE:IntelliJ IDEA(集成JProfiler插件)。
  4. 服务器环境:Linux(需配置OOM自动生成Dump文件)。

实战步骤:从OOM到问题定位

配置JVM参数生成Dump文件

Dump文件 是在OOM内存溢出的时候,自动Dump文件转存快照的,配置JVM参数 ,就能够在发生Out of Memory错误的时候,就是把当前堆栈信息转存为快照Dump文件

1
2
3
4
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dev/test_service_jvmDump.hprof

生产
     java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/app.hprof -jar app.jar
  1. HeapDumpOnOutOfMemoryError:触发OOM时生成快照。
  2. HeapDumpPath:指定快照文件存储路径(需确保目录可写)。 在这里插入图片描述

获取并解析Dump文件

  1. 当OOM发生时,服务器会生成.hprof文件,下载至本地。
  2. 使用JProfiler打开快照:
    • 启动JProfiler,选择 Open SnapshotsOpen a Single Snapshot
    • 加载.hprof文件后,JProfiler会自动解析堆内存结构。

在这里插入图片描述 导入成功后可以看到如下界面: 在这里插入图片描述

Jprofiler使用 分析大对象来源

Jprofile 分析对象,有两个特别重要的信息即 对象的引用信息

  • incoming references
    • 入引用, 显示这个对象被谁引用, 找问题出现的代码位置
  • outcoming references
    • 出引用,显示这个对象引用的其他对象, 找出他有什么,他为什么这么大内存,内存里面存储的是啥

下面我们先预估对象内存大小

按照Size排序,这个byte[]使用15350次,占用内存1272MB,看着很大 在这里插入图片描述 Incomming References 入引用,找引用当前对象的对象

Use select Objects 分析对象引用

首先 选中对象,点击右键,Use select Objects 在这里插入图片描述 选择 incoming references 找到对象引用的地方 在这里插入图片描述 逐个分析, 点击show more

在这里插入图片描述

查看代码,分析问题

在这里插入图片描述

Jprofile 大对象寻找法

上面我们通过 incomming references ,找对了对象的引用,下面我们我们采用更为直接的方法

我们都知道内存过高, 无法回收,肯定是内存中堆积的东西多了, 那么我们看下有哪些大对象占用了内存,如何找到大对象?

Jprofile提供了Biggest Objects的 查找方法

  • 我们可以看到按钮 Biggets OBjects
  • 直接点击按钮, JProfiler就会显示当前堆栈中有哪些大对象

在上面的基础上进行操作 在这里插入图片描述 然后点开大对象进行分析, 同样的 Used Selected Objects 在这里插入图片描述 点击Incomming References 查找对象引用信息

![![在这里插入图片描述](../../image/af4eba6408a6405f86d7a60748234e10.png) 同样的结果, 可以定位到148行代码存在问题 在这里插入图片描述

用Graph 查找对象源

先查找 Incomming References 找到对象被谁引用 找到想要追查的对象后, 选择User Selected Objects 在这里插入图片描述 在这里插入图片描述 然后点击 Show In Graph 定位线程及Class信息

在这里插入图片描述 然后根据 数据源Heap Walker 定位到问题的Class类信息及具体的行信息

在这里插入图片描述

Show Path To GC Root 找到创建该方法的位置

选择Use Selected Objects ,选择Imcoming References, 然后点击 Show Path To GC Root

从创建该对象的方法开始检查,检查所有用到该对象的地方,直到找到泄漏位置

选择All root, 展示所有的根节点链路信息 在这里插入图片描述 定位问题,查阅代码 在这里插入图片描述

总结

通过JProfiler分析Dump文件,开发者可以快速定位内存泄漏或大对象问题。关键在于:

  1. 生成准确的快照:确保JVM参数配置正确。
  2. 掌握分析工具的核心功能:如引用链追踪、大对象筛选。
  3. 结合代码与业务场景:避免“治标不治本”的临时修复。
未来的你,会感谢今天仍在努力奋斗的你