Java 为什么对象的大小与年龄n+;当前suvivor中的1比上一个suvivor中年龄为n的对象大?

Java 为什么对象的大小与年龄n+;当前suvivor中的1比上一个suvivor中年龄为n的对象大?,java,garbage-collection,jvm,jvm-hotspot,Java,Garbage Collection,Jvm,Jvm Hotspot,在尝试优化JVM GC标志时,我添加了-XX:+PrintTenuringDistribution来打印不同年龄段的对象大小分布,我发现了一个奇怪的现象 直观地说,当前GC进程中年龄为(n+1)的对象的大小应该小于上一个GC进程中年龄为n的对象的大小 第二个GC中年龄为2的对象是第一个GC中年龄为1的对象。假设第一个GC中年龄为1的活动对象的大小为S11,第二个GC中年龄为2的活动对象的大小为S22。然后S11>S22,因为一些1岁的物体会被破坏 但我看到的是: - age 1: 50

在尝试优化JVM GC标志时,我添加了
-XX:+PrintTenuringDistribution
来打印不同年龄段的对象大小分布,我发现了一个奇怪的现象

直观地说,当前GC进程中年龄为(n+1)的对象的大小应该小于上一个GC进程中年龄为n的对象的大小


第二个GC中年龄为2的对象是第一个GC中年龄为1的对象。假设第一个GC中年龄为1的活动对象的大小为S11,第二个GC中年龄为2的活动对象的大小为S22。然后S11>S22,因为一些1岁的物体会被破坏

但我看到的是:

- age   1:    5028488 bytes,    5028488 total
gc happened...
- age   2:    5030440 bytes,    7630688 total
gc happened...
- age   3:    6864328 bytes,   10406920 total
gc happened...
- age   4:   13155416 bytes,   17153720 total
gc happened...
- age   5:   11057632 bytes,   15633880 total
gc happened...
- age   6:   17349112 bytes,   22898584 total
正如我们看到的,它的大小增加了。我不知道为什么会这样。以下是完整的GC日志:

2017-08-30T13:22:33.821+0800: 219271.297: [GC (Allocation Failure) 
2017-08-30T13:22:33.821+0800: 219271.297: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    5028488 bytes,    5028488 total
- age   2:     394616 bytes,    5423104 total
- age   3:     414024 bytes,    5837128 total
- age   4:     851040 bytes,    6688168 total
- age   5:     462728 bytes,    7150896 total
- age   6:     526064 bytes,    7676960 total
: 1343960K->9188K(1504064K), 0.0105175 secs] 5697641K->4363292K(8221504K), 0.0106539 secs] [Times: user=0.11 sys=0.01, real=0.01 secs] 
2017-08-30T13:22:33.831+0800: 219271.308: Total time for which application threads were stopped: 0.0119211 seconds, Stopping threads took: 0.0001500 seconds
2017-08-30T13:22:34.486+0800: 219271.963: [GC (Allocation Failure) 2017-08-30T13:22:34.486+0800: 219271.963: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    2600248 bytes,    2600248 total
- age   2:    5030440 bytes,    7630688 total
- age   3:     392760 bytes,    8023448 total
- age   4:     413704 bytes,    8437152 total
- age   5:     850888 bytes,    9288040 total
- age   6:     462488 bytes,    9750528 total
: 1346148K->11226K(1504064K), 0.0103425 secs] 5700252K->4365843K(8221504K), 0.0104998 secs] [Times: user=0.11 sys=0.01, real=0.01 secs] 
2017-08-30T13:22:34.497+0800: 219271.973: Total time for which application threads were stopped: 0.0116511 seconds, Stopping threads took: 0.0000986 seconds
2017-08-30T13:22:35.151+0800: 219272.627: [GC (Allocation Failure) 2017-08-30T13:22:35.151+0800: 219272.627: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    3132664 bytes,    3132664 total
- age   2:     409928 bytes,    3542592 total
- age   3:    6864328 bytes,   10406920 total
- age   4:     392304 bytes,   10799224 total
- age   5:     413120 bytes,   11212344 total
- age   6:     588304 bytes,   11800648 total
: 1348186K->12885K(1504064K), 0.0109247 secs] 5702803K->4367954K(8221504K), 0.0110585 secs] [Times: user=0.11 sys=0.02, real=0.01 secs] 
2017-08-30T13:22:35.162+0800: 219272.638: Total time for which application threads were stopped: 0.0122836 seconds, Stopping threads took: 0.0001519 seconds
2017-08-30T13:22:35.841+0800: 219273.318: [GC (Allocation Failure) 2017-08-30T13:22:35.841+0800: 219273.318: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    2544776 bytes,    2544776 total
- age   2:    1045056 bytes,    3589832 total
- age   3:     408472 bytes,    3998304 total
- age   4:   13155416 bytes,   17153720 total
- age   5:     392008 bytes,   17545728 total
- age   6:     412920 bytes,   17958648 total
: 1349845K->19062K(1504064K), 0.0100055 secs] 5704914K->4374704K(8221504K), 0.0101450 secs] [Times: user=0.10 sys=0.02, real=0.01 secs] 
2017-08-30T13:22:35.851+0800: 219273.328: Total time for which application threads were stopped: 0.0113139 seconds, Stopping threads took: 0.0001079 seconds
2017-08-30T13:22:36.260+0800: 219273.736: Total time for which application threads were stopped: 0.0018019 seconds, Stopping threads took: 0.0003786 seconds
2017-08-30T13:22:36.521+0800: 219273.997: [GC (Allocation Failure) 2017-08-30T13:22:36.521+0800: 219273.997: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    2977976 bytes,    2977976 total
- age   2:     408656 bytes,    3386632 total
- age   3:     781704 bytes,    4168336 total
- age   4:     407912 bytes,    4576248 total
- age   5:   11057632 bytes,   15633880 total
- age   6:     391592 bytes,   16025472 total
: 1355810K->16950K(1504064K), 0.0107807 secs] 5711453K->4372995K(8221504K), 0.0109248 secs] [Times: user=0.11 sys=0.02, real=0.01 secs] 
2017-08-30T13:22:36.532+0800: 219274.008: Total time for which application threads were stopped: 0.0121995 seconds, Stopping threads took: 0.0001272 seconds
2017-08-30T13:22:37.214+0800: 219274.691: [GC (Allocation Failure) 2017-08-30T13:22:37.214+0800: 219274.691: [ParNew Desired survivor size 85557248 bytes, new threshold 6 (max 6)
- age   1:    3480256 bytes,    3480256 total
- age   2:     473344 bytes,    3953600 total
- age   3:     407336 bytes,    4360936 total
- age   4:     781080 bytes,    5142016 total
- age   5:     407456 bytes,    5549472 total
- age   6:   17349112 bytes,   22898584 total
公式
Size(年龄(n+1))
是错误的

以上面的
gc.log
为例,在第一个gc中,
大小(年龄(1))
5028488
,但在第二个gc中,
大小(年龄(1))
2600248
,这意味着对象生成速度比开始时要慢

因此,您将看到,在第二个gc中,
大小(年龄(2)
)是
5030440
,几乎等于第一个gc中的
大小(年龄(1))
,这使得它大于第二个gc中的
大小(年龄(1))

关键是生成速度是不断变化的。所以可能是
Size(年龄(n+1))
,或者可能是
Size(年龄(n+1))>Size(年龄(n))
,这都是可能的


希望我没有误解您的问题。

解决方案是仔细查看日志。您的输出显示为新的所需幸存者大小85557248字节,但查看上一个日志,您会看到组合空间消耗为22898584字节。这比幸存者能承受的更大。因此,基本上,您的年龄统计必须同时参考
幸存者
终身


我假设,您有一些年龄为2/3/4/5/6的对象,这些对象已升级为
终身
,并且不受发生的集合的影响。

第二次GC中年龄为2的对象是第一次GC中年龄为1的对象。假设第一个GC中年龄为1的活动对象的大小为S11,第二个GC中年龄为2的活动对象的大小为S22。然后S11>S22,因为一些年龄为1的对象被销毁。在第一次GC和第二次GC之间生成的那些对象的年龄应该是1,而不是2。难道这些对象不是越来越多而是在增长吗?比如说,一个具有引用的对象,在第一次收集期间为
null
,但在下一次迭代期间变为引用实际对象?在下一次迭代期间引用的新对象有其自身的年龄