• 44 UseParallelGC的场景下 只发生了 minorgc, oldGen 里面却被占用了空间


    前言

    呵呵 最近在某交流群里面 有同学提到了这样的一个问题  

    最开始 我没有怎么注意, 但是 问题持续了两天, 呵呵 然后 花了一些时间看了一下 

    Nerazzurri : 我看了个测试环境上部的应用的GC日志,看到有些信息不太明白,第一次YGC,堆占用空间和年轻代一样,那是说老年代没有被占用,第二次YGC就不一样,年轻代比堆少8K,第三次少16K,第三次少32K,不知道这些少的,是不是在老年代,而且这些数还是2的倍数,不知道是什么原因,不能仅仅是巧合吧,
    然后第五次GC原因,GCLocker Initiated GC指什么?
    然后后面的第一次FullGC ,是由于元空间不够触发的吗?看着年轻代占用并不多 

    North : 这个怎么解释

    North : 这24k数据是怎么进去的呢

    然后 之后洗了一个 case, 来测试一下, 问题 果然复现了 

    问题的原因虽然找到了, 但是 这个问题的原因的更细节的东西, 就了解的少之又少了 

    以下测试用例截图基于 jdk9 调试 

    另外有一篇类似的问题, 也和本文的内容有一些关联 UseConcMarkSweepGC 的情况下 PrintTenuringDistribution 和 PrintGCDetails 的对象空间占用不一致的问题

    测试用例 

    1. /**
    2. * Test11OldUnknown8Kb
    3. *
    4. * @author Jerry.X.He <970655147@qq.com>
    5. * @version 1.0
    6. * @date 2021-10-27 19:09
    7. */
    8. public class Test11OldUnknown8Kb {
    9. // Test11OldUnknown8Kb
    10. // -Xmx100M -XX:+UseParallelGC -XX:ParallelGCThreads=10 -XX:OldPLABSize=10240 -XX:+PrintHeapAtGC -XX:+PrintGCDetails
    11. public static void main(String[] args) throws Exception {
    12. for (int i = 0; i < 70; i++) {
    13. byte[] dummy = new byte[1 * 1024 * 1024];
    14. }
    15. System.in.read();
    16. }
    17. }

    然后配置 vm 参数, 运行, 大致会得到日志如下 

    可以参照 HeapBefore, HeapAfter, 发现 第二次 minor gc 之后 oldGen 增加了 80k, 第三次 minor gc 的时候 oldGen 又增加了 80k 

    这里的差异是 80k, 上面的对话差异是 8k, 这里先剧透一下, 是和 OldPLABSize 的参数配置有关系 

    1. {Heap before GC invocations=1 (full 0):
    2. PSYoungGen total 29696K, used 25207K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    3. eden space 25600K, 98% used [0x00000007bdf00000,0x00000007bf79de48,0x00000007bf800000)
    4. from space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
    5. to space 4096K, 0% used [0x00000007bf800000,0x00000007bf800000,0x00000007bfc00000)
    6. ParOldGen total 68608K, used 0K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    7. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c00000,0x00000007bdf00000)
    8. Metaspace used 3075K, capacity 4556K, committed 4864K, reserved 1056768K
    9. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    10. [GC (Allocation Failure) [PSYoungGen: 25207K->2524K(29696K)] 25207K->2524K(98304K), 0.0034964 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
    11. Heap after GC invocations=1 (full 0):
    12. PSYoungGen total 29696K, used 2524K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    13. eden space 25600K, 0% used [0x00000007bdf00000,0x00000007bdf00000,0x00000007bf800000)
    14. from space 4096K, 61% used [0x00000007bf800000,0x00000007bfa77250,0x00000007bfc00000)
    15. to space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
    16. ParOldGen total 68608K, used 0K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    17. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c00000,0x00000007bdf00000)
    18. Metaspace used 3075K, capacity 4556K, committed 4864K, reserved 1056768K
    19. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    20. }
    21. {Heap before GC invocations=2 (full 0):
    22. PSYoungGen total 29696K, used 27602K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    23. eden space 25600K, 97% used [0x00000007bdf00000,0x00000007bf77d6d8,0x00000007bf800000)
    24. from space 4096K, 61% used [0x00000007bf800000,0x00000007bfa77250,0x00000007bfc00000)
    25. to space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
    26. ParOldGen total 68608K, used 0K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    27. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c00000,0x00000007bdf00000)
    28. Metaspace used 3085K, capacity 4556K, committed 4864K, reserved 1056768K
    29. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    30. [GC (Allocation Failure) [PSYoungGen: 27602K->1613K(29696K)] 27602K->1693K(98304K), 0.0016530 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
    31. Heap after GC invocations=2 (full 0):
    32. PSYoungGen total 29696K, used 1613K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    33. eden space 25600K, 0% used [0x00000007bdf00000,0x00000007bdf00000,0x00000007bf800000)
    34. from space 4096K, 39% used [0x00000007bfc00000,0x00000007bfd93658,0x00000007c0000000)
    35. to space 4096K, 0% used [0x00000007bf800000,0x00000007bf800000,0x00000007bfc00000)
    36. ParOldGen total 68608K, used 80K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    37. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c14000,0x00000007bdf00000)
    38. Metaspace used 3085K, capacity 4556K, committed 4864K, reserved 1056768K
    39. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    40. }
    41. {Heap before GC invocations=3 (full 0):
    42. PSYoungGen total 29696K, used 26933K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    43. eden space 25600K, 98% used [0x00000007bdf00000,0x00000007bf7ba130,0x00000007bf800000)
    44. from space 4096K, 39% used [0x00000007bfc00000,0x00000007bfd93658,0x00000007c0000000)
    45. to space 4096K, 0% used [0x00000007bf800000,0x00000007bf800000,0x00000007bfc00000)
    46. ParOldGen total 68608K, used 80K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    47. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c14000,0x00000007bdf00000)
    48. Metaspace used 3086K, capacity 4556K, committed 4864K, reserved 1056768K
    49. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    50. [GC (Allocation Failure) [PSYoungGen: 26933K->1469K(29696K)] 27013K->1629K(98304K), 0.0017334 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
    51. Heap after GC invocations=3 (full 0):
    52. PSYoungGen total 29696K, used 1469K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    53. eden space 25600K, 0% used [0x00000007bdf00000,0x00000007bdf00000,0x00000007bf800000)
    54. from space 4096K, 35% used [0x00000007bf800000,0x00000007bf96f668,0x00000007bfc00000)
    55. to space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
    56. ParOldGen total 68608K, used 160K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    57. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c28000,0x00000007bdf00000)
    58. Metaspace used 3086K, capacity 4556K, committed 4864K, reserved 1056768K
    59. class space used 324K, capacity 392K, committed 512K, reserved 1048576K
    60. }
    61. Disconnected from the target VM, address: '127.0.0.1:51462', transport: 'socket'
    62. Heap
    63. PSYoungGen total 29696K, used 15785K [0x00000007bdf00000, 0x00000007c0000000, 0x00000007c0000000)
    64. eden space 25600K, 55% used [0x00000007bdf00000,0x00000007becfaea8,0x00000007bf800000)
    65. from space 4096K, 35% used [0x00000007bf800000,0x00000007bf96f668,0x00000007bfc00000)
    66. to space 4096K, 0% used [0x00000007bfc00000,0x00000007bfc00000,0x00000007c0000000)
    67. ParOldGen total 68608K, used 160K [0x00000007b9c00000, 0x00000007bdf00000, 0x00000007bdf00000)
    68. object space 68608K, 0% used [0x00000007b9c00000,0x00000007b9c28000,0x00000007bdf00000)
    69. Metaspace used 3093K, capacity 4556K, committed 4864K, reserved 1056768K
    70. class space used 325K, capacity 392K, committed 512K, reserved 1048576K

    基于 hprof 的调试 

     jmap dump 堆dump文件, 然后使用 jhat 解析 如下, 总共有 20774 个 oop 

    然后使用 UseConcMarkSweepGC 的情况下 PrintTenuringDistribution 和 PrintGCDetails 的对象空间占用不一致的问题​​​​​​​z

    中的 Test08ParseFromDumpFile​​​​​​​ 来进行分析, 结果如下 

    可以看到 old 里面确实是有 oop, 大致的占用也在 160kb 左右  

    根据地址信息 调整一下 oop 的排列, oldGen 第三次 gc 之后正常 oop 排列如下 

    1. 0x7b9c00000 - java.lang.Class - 108 - class java.lang.ref.Finalizer (108 bytes)
    2. 0x7b9c00078 - java.lang.Class - 108 - class java.lang.ref.ReferenceQueue (108 bytes)
    3. 0x7b9c000f0 - java.lang.Class - 108 - class sun.misc.VM (108 bytes)
    4. 0x7b9c001a0 - java.lang.Class - 108 - class java.lang.ref.Reference (108 bytes)
    5. 0x7b9c00210 - [I - 81392 - null
    6. 0x7b9c14000 - java.lang.Object - 16 - null
    7. 0x7b9c14010 - java.lang.String - 28 - Negative timeout value (28 bytes)
    8. 0x7b9c14028 - [I - 81880 - null

    第二次 minor gc  之后有 4 个 Class 对象 promote 到了 oldGen, 然后 gc 之后 retire plab, 填充了一个 int[81392] 

    第三次 minor gc  之后有 1 个 Object 对象, 1 个 String 对象 promote 到了 oldGen, 然后 gc 之后 retire plab, 填充了一个 int[81880] 

    但是 据此, 我们能够明确 oldGen 中是那些对象, 但是 不能明确具体的原因 

    所以 还得基于 vm 来调试一下 

    基于 VM 的调试

    然后可以看到在 miinor gc 的时候, 确实是有 oop promote 到 oldGen 

    然后 我们再来看一下 他的具体的原因 

    调整一下 栈帧, 可以看到这里的 promotion_immediately, 然后 copy_to_survivor 的时候, 不会在 young 分配空间, 直接在 old 里面分配空间  

    在往上看一看, 这里是在处理 codecache 里面关联的一部分 oop, 也就是说 codecache 里面会有一部分 oop 会直接 promote 到 oldGen 

     搜索一下 roots_to_old_closure 使用的地方, 只有这里; 搜索一下 PSPromoteRootsClosure 使用的地方, 也只有这里 

    为什么差异是 80k

    回到另外一个问题, "这里的差异是 80k, 上面的对话差异是 8k, 这里先剧透一下, 是和 OldPLABSize 的参数配置有关系" 

    呵呵 这个就不用解释了吧 

    如果您还没有懂, 请重新阅读一下本文, 以及参考文章 

    完 

    参考

    UseConcMarkSweepGC 的情况下 PrintTenuringDistribution 和 PrintGCDetails 的对象空间占用不一致的问题

  • 相关阅读:
    基于STM32的智能小车--电机驱动设计
    一百八十九、ClickHouse——在海豚调度器中执行ClickHouse建库建表语句
    dump_stack()
    关于#深度学习#的问题:深度学习代码使用环境的cuda版本是10.0(语言-python)
    Nacos2.1.2源码修改支持高斯,postresql
    微信小程序简介
    MyBatis-Plus-扩展操作(3)
    智能小车循迹与避障运动控制系统的设计
    【虹科】无/低代码系统如何推动制造业的检测应用
    基于C++MFC的活塞环外观表面缺陷机器视觉检测系统
  • 原文地址:https://blog.csdn.net/u011039332/article/details/121049206