基于DevKit Java性能分析工具的调优实践——G1巨型对象触发GC问题
发表于 2025/12/29
0
1 调优概述
鲲鹏DevKit是一款提供涵盖迁移、测试、性能调优及系统诊断等各环节的开发使能工具集。其中,DevKit Java性能分析工具是针对基于鲲鹏的服务器上运行的Java程序的性能分析和优化工具,能图形化显示Java程序的堆、线程、锁、垃圾回收等信息,收集热点函数、定位程序瓶颈点,帮助用户采取针对性优化。本文使用Java性能优化工具对运行中的Java程序进行在线分析和采样分析,找到程序中的G1巨型对象触发GC问题,并根据分析结果进行优化修改,从而实现Java程序最佳运行。
2 环境要求
|
项目 |
说明 |
|
服务器 |
TaiShan 200 服务器(型号2280) |
|
CPU |
Kunpeng 920 |
|
OS |
CentOS 7.6 |
|
调优工具 |
Kunpeng DevKit Java性能分析工具 |
3 前提条件
- 服务器和操作系统正常运行。
- PC端已经安装SSH远程登录工具
- 需要优化的Java程序
4 调优思路
- 使用Java性能优化工具对Java进程进行在线分析;
- 使用Java性能优化工具对Java进程进行采样分析
- 针对性能的瓶颈点进行性能优化;
- 观察优化后的Java程序,判断问题是否解决
5 调优过程
5.1 对程序进行在线分析,切换到GC页签
发现有些GC原因是巨型对象的分配造成的

5.2 对程序进行采样分析,切到GC页签
会得到一份优化建议报告


5.3 采样分析切换到 内存-->老年代对象页签
在某些情况下,如果巨型对象的生命周期比较长,则在该页签下可以采集到对象的相关信息,也会得到一份报告,可以得知巨型对象的具体信息


根据相关信息,可以得出结论采集的巨型对象是在同一个线程中创建的,巨型对象为2Mib 大小的 byte[],可以根据堆栈搜索代码,看看具体的逻辑。
5.4 在线分析执行内存转储
如果通过采样分析不能直接采集到巨型对象,可以通过得知的 region 大小,我们从堆转储分析中找找相应的线索
5.4.1 步骤一:直方图中找堆占用较多的嫌疑类

5.4.2 步骤二:查看每个嫌疑类的所有对象

发现 频繁分配了 byte[],大小为 2Mib,符合巨型对象要求,继续定位
5.4.3 步骤三:支配树查找线索
支配树中发现一个线程保留堆大小跟直方图中byte[]的保留堆大小差不多

展开发现 这个线程中有个List 持有创建的巨型对象

查看从byte[]到GC Roots的路径

5.5 程序代码定位
根据采样分析和堆转储的分析,查找程序中的相关代码,本案例的demo不复杂,根据采样分析提供的类名: DockerTestController ,巨像对象为byte[], 分配大小为2Mib,List持有巨型对象等线索,直接找到了具体的代码
5.6 优化后的 Java程序
本demo通过设置调大 region 大小的方式解决该问题
6 实践总结
本次实践中,通过采样分析和堆转储分析定位代码中具体巨型对象分配的位置,通过调大region 大小解决。但是在实际的业务中,优先建议调整代码逻辑去解决问题,尽量避免分配巨型对象,从而减轻jvm的压力。 如果发现默认的region大小,不符合程序的体量,那么可以根据实际情况适当调大region大小。
在进行其他程序调优时,需要根据鲲鹏DevKit性能优化工具采集分析的实际结果和对应的优化建议进行调优操作。具体的调优思路可以参考本次实践。


