美文网首页
一探究竟-跟踪G1老年代晋升对象

一探究竟-跟踪G1老年代晋升对象

作者: yuanjian | 来源:发表于2023-11-25 13:13 被阅读0次

    背景

        现网服务频繁YGC,每次YGC都会有对象晋升老年代,造成频繁混合回收。但是程序中接口执行很快,平均响应时长在10ms,理论上不该产生老年代对象。
        到底什么对象在晋升?如果能够定位晋升对象,我们就可以对程序做进一步的优化,下面我们来介绍在G1垃圾收集器中如何快速定位YGC后晋升到老年代中的对象。

    实践

    环境:java11

    java版本
    1. 启动脚本增加参数: -XX:+UseG1GC -Xlog:gc*,region*=trace:./gc.log:time

    2. 在程序进行混合回收前打DUMP
          注意:建议在打印dump前先压缩gc日志,否则dump后产生的GC日志可能会影响排查过程。

    3. 查找有老年代对象晋升的YGC
      通过脚本grep "Old regions:" gc.log查看 old region变化

      对象晋升情况

      发现第24次GC有大量对象晋升

    4. 对象晋升一定会分配新的老年代分区,使用命令查询第24次GC老年代的分配情况

        命令:grep 'GC(24)' gc.log | grep 'ALLOC(OLD)',用于查找第24次GC分配的老年代分区。

    老年代分区分配情况
    1. 我们根据内存地址查询第24次GC的分配和使用情况

      命令:grep 'GC(24)' gc.log | grep '0x00000007c3200000'

      分区使用情况

        图中可发现此region从F变为了O(空闲region转变为老年代region),表示有对象晋升到此region。region地址:0x00000007c3200000,0x00000007c3300000
        我们可以使用相同的方法查看其它region的晋升情况,并找到晋升的内存地址。
        注意:[] 中的三个16进制数,分别为region的起始地址、当前已使用到的地址、结束地址

    1. 使用MAT工具打开DUMP文件,并使用OQL根据region地址进行查找

        命令:SELECT * FROM INSTANCEOF java.lang.Object t WHERE toHex(t.@objectAddress)>="0x7c3300000" AND toHex(t.@objectAddress)<="0x7c3400000"

    image-20231122232859764.png

    注意:查找条件中的内存地址需要将前面连续的0去掉。

    相关文章

      网友评论

          本文标题:一探究竟-跟踪G1老年代晋升对象

          本文链接:https://www.haomeiwen.com/subject/yyrowdtx.html