jvm-对象年龄(-XX:+PrintTenuringDistribution)

0.701字数 594阅读 3119
-XX:+PrintTenuringDistribution 赠送银弹: -XX:SurvivorRatio

    作用:输出显示在survivor空间里面有效的对象的岁数情况。

{Heap before GC invocations=0 (full 0):
 par new generation   total 1887488K, used 1677824K [0x00000006e0c00000, 0x0000000760c00000, 0x0000000760c00000)
  eden space 1677824K, 100% used [0x00000006e0c00000, 0x0000000747280000, 0x0000000747280000)
  from space 209664K,   0% used [0x0000000747280000, 0x0000000747280000, 0x0000000753f40000)
  to   space 209664K,   0% used [0x0000000753f40000, 0x0000000753f40000, 0x0000000760c00000)
 concurrent mark-sweep generation total 2097152K, used 0K [0x0000000760c00000, 0x00000007e0c00000, 0x00000007e0c00000)
 concurrent-mark-sweep perm gen total 512000K, used 22205K [0x00000007e0c00000, 0x0000000800000000, 0x0000000800000000)
2018-02-06T13:29:54.526+0800: 6.958: [GC2018-02-06T13:29:54.526+0800: 6.958: [ParNew2018-02-06T13:29:54.584+0800: 7.016: [SoftReference, 0 refs, 0.0000450 secs]2018-02-06T13:29:54.584+0800: 7.016: [WeakReference, 1074 refs, 0.0001630 secs]2018-02-06T13:29:54.584+0800: 7.017: [FinalReference, 67745 refs, 0.1348760 secs]2018-02-06T13:29:54.719+0800: 7.152: [PhantomReference, 0 refs, 0.0000180 secs]2018-02-06T13:29:54.719+0800: 7.152: [JNI Weak Reference, 0.0000090 secs]
Desired survivor size 107347968 bytes, new threshold 1 (max 30)
- age   1:  157548032 bytes,  157548032 total
: 1677824K->154017K(1887488K), 0.1942010 secs] 1677824K->154017K(3984640K), 0.1942870 secs] [Times: user=0.20 sys=0.08, real=0.19 secs] 
Heap after GC invocations=1 (full 0):
 par new generation   total 1887488K, used 154017K [0x00000006e0c00000, 0x0000000760c00000, 0x0000000760c00000)
  eden space 1677824K,   0% used [0x00000006e0c00000, 0x00000006e0c00000, 0x0000000747280000)
  from space 209664K,  73% used [0x0000000753f40000, 0x000000075d5a8560, 0x0000000760c00000)
  to   space 209664K,   0% used [0x0000000747280000, 0x0000000747280000, 0x0000000753f40000)
 concurrent mark-sweep generation total 2097152K, used 0K [0x0000000760c00000, 0x00000007e0c00000, 0x00000007e0c00000)
 concurrent-mark-sweep perm gen total 512000K, used 22205K [0x00000007e0c00000, 0x0000000800000000, 0x0000000800000000)
}

其中-XX:+PrintTenuringDistribution只是丰富了gclog部分如下:

Desired survivor size 107347968 bytes, new threshold 1 (max 30)
- age   1:  157548032 bytes,  157548032 total
: 1677824K->154017K(1887488K), 0.1942010 secs] 1677824K->154017K(3984640K), 0.1942870 secs] [Times: user=0.20 sys=0.08, real=0.19 secs] 

描述信息:
    Survivor对象年龄,最大值设置的是30,实际计算后的阀值是1。
    Survivor大小,Desired survivor size指的是整个Survivor的1/2 107347968byte也就是 from or to 的大小,所以例子中的Survivor大小是204mb 对象阀值是1,从这个例子中可以看出进入survivor的对象比survivor预留空间大,所以会有对象到老年代中。这时最好要调整-XX:SurvivorRatio来设置合理的Survivor
    Survivor中存活对象157mb,切年龄是1。

赠送银弹

    额外赠送-XX:SurvivorRatio=8 含义:eden/suvivor=8 ,其中survivor包含from、to。
eg:yong区设定2g,-XX:NewSize=2g ,那么,from = 2g/(8+2) ,也就是说yong区会被分成10分,eden区占8分,survivor占2份,这也能看出比值越大survivor被稀释的越严重。比值越小survivor分到的空间更大。
    以上面log为例,计算出合理的-XX:SurvivorRatio ,可以确定survivor为160mb*2为合理区域,所以假设比值为x,eden=320x,yong区总共 2g=320x+320,所以比值x=(2g-320)/320 ,x近似=5。

继续分析log中的age

截取运行过一段时间的日志分析下:

{Heap before GC invocations=11 (full 0):
 par new generation   total 1887488K, used 1716581K [0x00000006e0c00000, 0x0000000760c00000, 0x0000000760c00000)
  eden space 1677824K, 100% used [0x00000006e0c00000, 0x0000000747280000, 0x0000000747280000)
  from space 209664K,  18% used [0x0000000753f40000, 0x00000007565196a8, 0x0000000760c00000)
  to   space 209664K,   0% used [0x0000000747280000, 0x0000000747280000, 0x0000000753f40000)
 concurrent mark-sweep generation total 2097152K, used 23205K [0x0000000760c00000, 0x00000007e0c00000, 0x00000007e0c00000)
 concurrent-mark-sweep perm gen total 512000K, used 49938K [0x00000007e0c00000, 0x0000000800000000, 0x0000000800000000)
2018-02-06T14:21:29.610+0800: 3102.042: [GC2018-02-06T14:21:29.610+0800: 3102.042: [ParNew2018-02-06T14:21:29.639+0800: 3102.072: [SoftReference, 0 refs, 0.0000400 secs]2018-02-06T14:21:29.639+0800: 3102.072: [WeakReference, 9421 refs, 0.0005540 secs]2018-02-06T14:21:29.640+0800: 3102.072: [FinalReference, 4196 refs, 0.0044150 secs]2018-02-06T14:21:29.644+0800: 3102.077: [PhantomReference, 4 refs, 0.0000080 secs]2018-02-06T14:21:29.644+0800: 3102.077: [JNI Weak Reference, 0.0000090 secs]
Desired survivor size 107347968 bytes, new threshold 16 (max 30)
- age   1:    4345400 bytes,    4345400 total
- age   2:    2436856 bytes,    6782256 total
- age   3:     676112 bytes,    7458368 total
- age   4:    2323952 bytes,    9782320 total
- age   5:     599616 bytes,   10381936 total
- age   6:     563656 bytes,   10945592 total
- age   7:     567656 bytes,   11513248 total
- age   8:     815480 bytes,   12328728 total
- age   9:     527672 bytes,   12856400 total
- age  10:    3956032 bytes,   16812432 total
- age  11:   16575184 bytes,   33387616 total
: 1716581K->49462K(1887488K), 0.0345690 secs] 1739786K->72667K(3984640K), 0.0349280 secs] [Times: user=0.12 sys=0.00, real=0.04 secs] 
Heap after GC invocations=12 (full 0):
 par new generation   total 1887488K, used 49462K [0x00000006e0c00000, 0x0000000760c00000, 0x0000000760c00000)
  eden space 1677824K,   0% used [0x00000006e0c00000, 0x00000006e0c00000, 0x0000000747280000)
  from space 209664K,  23% used [0x0000000747280000, 0x000000074a2cd8a0, 0x0000000753f40000)
  to   space 209664K,   0% used [0x0000000753f40000, 0x0000000753f40000, 0x0000000760c00000)
 concurrent mark-sweep generation total 2097152K, used 23205K [0x0000000760c00000, 0x00000007e0c00000, 0x00000007e0c00000)
 concurrent-mark-sweep perm gen total 512000K, used 49938K [0x00000007e0c00000, 0x0000000800000000, 0x0000000800000000)
}

格式:- age 年龄: 处于当前年龄段的对象大小 总大小(各个年龄段是累计的)

总结6:

    -XX:+PrintTenuringDistribution这个参数对于设置-XX:MaxTenuringThreshold有很大帮助,阀值需要长时间观察对象分布,设置合理即可。
    -XX:MaxTenuringThreshold设置过大问题:原本应该晋升对象到survivor区,直到survivor区溢出,一旦溢出发生,Eden+Svuvivor中对象将不再依据年龄全部提升到老年代,这样对象老化的机制就失效了
    -XX:MaxTenuringThreshold设置过小:eden区的对象会陆续送入old区,对象移动本身就是开销,cms老年代回收还会造成碎片化。

传送门jvm-对象动态年龄计算规则

推荐阅读更多精彩内容