MaxTenuringThreshold 参数

MaxTenuringThreshold这个参数用于控制对象能经历多少次Minor GC才晋升到旧生代,默认值是15,那是不是意味着对象要经历15次minor gc才晋升到旧生代呢,来看下面的一个例子。

public class GCTenuringThreshold{
public static void main(String[] args) throws Exception{
GCMemoryObject object1=new GCMemoryObject(2);
GCMemoryObject object2=new GCMemoryObject(8);
GCMemoryObject object3=new GCMemoryObject(8);
GCMemoryObject object4=new GCMemoryObject(8);
object2=null;
object3=null;
GCMemoryObject object5=new GCMemoryObject(8);
Thread.sleep(4000);
object2=new GCMemoryObject(8);
object3=new GCMemoryObject(8);
object2=null;
object3=null;
object5=null;
GCMemoryObject object6=new GCMemoryObject(8);
Thread.sleep(5000);
}
}
class GCMemoryObject{
private byte[] bytes=null;
public GCMemoryObject(int multi){
bytes=new byte[1024*256*multi];
}
}

以-Xms20M –Xmx20M –Xmn10M –XX:+UseSerialGC参数执行以上代码,通过jstat -gcutil [pid] 1000 10的方式查看执行效果,很惊讶执行结果竟然是在第二次minor GC的时候object1就被晋升到old中了,而可以肯定的是这个时候to space空间是充足的,也就是说并不是在to space空间充足的情况下,对象一定要经历MaxTenuringThreshold次才会晋升到old,那具体规则到底是怎么样的呢,翻看Hotspot 6 update 21中SerialGC的实现,可以看到在每次minor GC后,会对这个存活周期的阈值做计算,计算的代码如下:

size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
size_t total = 0;
int age = 1;
assert(sizes[0] == 0, "no objects with age zero should be recorded");
while (age < table_size) {
total += sizes[age];
// check if including objects of age 'age' made us pass the desired
// size, if so 'age' is the new threshold
if (total > desired_survivor_size) break;
age++;
}
int result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;

其中desired_survivor_size是指survivor space/2,从上面的代码可看出,在计算存活周期这个阈值时,hotspot会遍历所有age的table,并对其所占用的大小进行累积,当累积的大小超过了survivor space的一半时,则以这个age作为新的存活周期阈值,最后取age和MaxTenuringThreshold中更小的一个值。

按照这样的规则,上面的运行效果就可验证了,第一次minor gc的时候存活周期的阈值为MaxTenuringThreshold,minor gc结束后计算出新的阈值为1,在第二次minor gc时object 1的age已经是1了,因此object1被晋升到了旧生代。

这个规则对于Serial GC以及ParNew GC(但对于开启了UseAdaptiveSizePolicy的ParNew GC而言也无效,默认是不开启的)均有效,对于PS(Parallel Scavenge) GC而言,在默认的情况下第一次以InitialTenuringThreshold(默认为7)为准,之后在每次minor GC后均会动态计算,规则比上面的复杂,后续再另写一篇blog来说,在设置-XX:-UseAdaptiveSizePolicy后,则以MaxTenuringThrehsold为准,并且不会重新计算,会是恒定值。

如希望跟踪每次minor GC后新的存活周期的阈值,可在启动参数上增加:-XX:+PrintTenuringDistribution,输出的信息中的:
Desired survivor size 1048576 bytes, new threshold 7 (max 15)
new threshold 7即标识新的存活周期的阈值为7。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值