JVM 对象动态年龄判断
JVM 对象动态年龄判断是怎么回事?虚拟机并不是永远地要求对象年龄必须达到了-XX:MaxTenuringThreshold=15才能晋升老年代;动态年龄判断: Survivor区的对象年龄从小到大进行累加,当累加到X年龄(某个年龄)时占用空间的总和大于50%(可以使用-XX:TargetSurvivorRatio=?来设置保留多少空闲空间,默认值是50),那么比X年龄大的对象都会晋升到老年代;.
JVM 对象动态年龄判断是怎么回事?
虚拟机并不是永远地要求对象年龄必须达到了-XX:MaxTenuringThreshold=15才能晋升老年代;
动态年龄判断: Survivor区的对象年龄从小到大进行累加,当累加到X年龄(某个年龄)时占用空间的总和大于50%(可以使用-XX:TargetSurvivorRatio=?来设置保留多少空闲空间,默认值是50),那么比X年龄大的对象都会晋升到老年代;
《深入理解Java虚拟机》中有如上的一段描述,讲的是动态对象年龄判定,避免-XX:MaxTenuringThreshold 设置过大导致大量对象无法晋升。但是存在一个问题,如果说非得相同年龄所有对象大小总和大于Survivor空间的一半才能晋升,按照如下场景:
- MaxTenuringThreshold为15
- 年龄1的对象占用了33%
- 年龄2的对象占用33%
- 年龄3的对象占用34%。
得出推论:
- 按照晋升的标准。首先年龄不满足MaxTenuringThreshold,不会晋升。
- 每个年龄的对象都不满足50%,不会晋升。
Survivor都占用了100%了,但是对象就不晋升。导致老年代明明有空间,但是对象就停留在年轻代。但这个结论似乎与jvm的表现不符合,只要老年代有空间,最后还会晋升的。
把晋升年龄计算的代码摘出,我们来看看动态年龄的计算:
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
//survivor_capacity是survivor空间的大小
size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
size_t total = 0;
uint age = 1;
while (age < table_size) {
total += sizes[age];//sizes数组是每个年龄段对象大小
if (total > desired_survivor_size) break;
age++;
}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
...
}
代码中有一个TargetSurvivorRatio的值。
-XX:TargetSurvivorRatio (目标存活率,默认为50%)
根据代码可以看到,动态年龄计算方式为:
- 通过这个比率来计算一个期望值,desired_survivor_size 。
- 然后用一个total计数器,累加每个年龄段对象大小的总和。
- 当total大于desired_survivor_size 停止。
- 然后用当前age和MaxTenuringThreshold 对比找出最小值作为结果。
总体表征就是,年龄从小到大进行累加,当加入某个年龄段后,累加和超过survivor区域*TargetSurvivorRatio的时候,就从这个年龄段网上的年龄的对象进行晋升。
所以上面的场景,年龄1的占用了33%,年龄2的占用了33%,累加和超过默认的TargetSurvivorRatio(50%),年龄2和年龄3的对象都要晋升。
动态对象年龄判断,主要是被TargetSurvivorRatio这个参数来控制。而且算的是年龄从小到大的累加和,而不是某个年龄段对象的大小。
更多推荐
所有评论(0)