G1GC老年代对象识别、回收对象类型及内存范围查询问询
针对G1GC Java 8应用内存分析的问题解答
1. 识别当前驻留在老年代的对象
G1的老年代由离散的Old Region组成,可通过以下方式定位其中的对象:
- MAT结合对象年龄筛选:
- 先给JVM添加参数
-XX:+PrintTenuringDistribution,从GC日志中获取对象晋升到老年代的阈值(tenuring threshold)。 - 在MAT中打开堆转储,使用OQL查询筛选年龄达到或超过阈值的对象:
SELECT * FROM INSTANCEOF java.lang.Object WHERE tenureAge >= ${你的晋升阈值} - 也可在MAT的「Histogram」视图右键选择「Group by Generation」,直接按逻辑分代查看老年代对象(需确保MAT版本适配Java 8的G1实现)。
- 先给JVM添加参数
- JVM命令辅助验证:
执行jmap -histo:live <pid>,输出的存活对象中,年龄超过晋升阈值的即为老年代对象;结合-XX:+PrintTenuringDistribution输出的GC日志,可对应堆转储中的对象分布。
2. 确定Full GC期间回收的对象类型
Full GC后的堆转储仅保留存活对象,需通过前后堆转储对比或增强GC日志输出实现:
- 堆转储对比法:
- 配置JVM参数
-XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC,让JVM在Full GC前后自动生成堆转储文件(命名格式为java_pid<pid>_beforeFullGC.hprof和java_pid<pid>_afterFullGC.hprof)。 - 在MAT中依次打开两个堆转储,点击菜单栏「Tools」→「Compare Memory Dumps」,选择两个文件后即可查看被回收对象的类型、数量及大小。
- 配置JVM参数
- GC日志直方图法:
开启参数-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC,Full GC前后会打印类的内存占用直方图,对比前后直方图中消失的类及数量,即可确定被回收的对象类型。
3. 获取G1GC老年代区域的内存地址范围
可通过以下命令或日志获取G1 Old Region的地址范围:
- GC日志输出:
添加参数-XX:+PrintHeapAtGC,每次GC时日志会打印所有Region的起始地址、大小及类型(Young/Old/Humongous),示例输出:Old regions: 512-1023 [0x0000000760000000, 0x0000000780000000)
- jcmd命令查询:
执行jcmd <pid> GC.heap_info(需Java 8u40及以上版本),输出中会列出每个Old Region的起始地址、结束地址及状态。 - jmap命令查询:
执行jmap -heap <pid>,在G1堆结构部分可看到Old Regions的地址范围汇总及单个Region的详细信息。 - HotSpot Serviceability Agent(SA):
若上述命令无法获取,可使用jhsdb jmap --heap --pid <pid>(JDK自带工具),能精准输出每个Region的地址和类型。
内容的提问来源于stack exchange,提问作者Tablo_Jhin
相关产品推荐
相关产品推荐

