survivor区对象何时进入老年代(深入理解jvm中表述不准确的地方)

《深入理解Java虚拟机》中关于Survivor区对象晋升老年代的描述可能存在误导,实际HotSpot虚拟机的判断标准是,当Survivor空间中年龄小于等于age的对象占比超过TargetSurvivorRatio时,大于age的对象会进入老年代。TargetSurvivorRatio默认为50%,可通过-XX:TargetSurvivorRatio参数调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们都知道,survivor区中的对象年龄超过MaxTenuringThreshold后会晋升到老年代,但实际上,只要survivor区中某个年龄段的对象超过一定比例后,大于这个年龄段的对象就会晋升到老年区。
对此,《深入理解java虚拟机》中原话是这样说的:如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。
我在第一次看到这个相同年龄时,就感觉不太对劲。假设下面这种情况:

年龄比例
130%
230%
330%

如果计算的是相同年龄所有对象的大小,那么任何一个年龄段的对象都没有超过50的占比,也就不会晋升到老年代,但实际上survivor已经使用了90%,这显然是不合理的。
翻看hotspot源码,hotspot并不是用的相同年龄:

uint ageTable::compute_tenuring_threshold(size_t survivor_capacity) {
  size_t desired_survivor_size = (size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);
  size_t total = 0;
  uint 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++;
  }
  uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;
  ......
  }

首先,在这段代码中,我们可以清晰地看到TargetSurvivorRatio这个变量,他是用来确定survivor区存活比例的。TargetSurvivorRatio默认为50,也就是书中所说的一半,具体大小可以用
-XX:TargetSurvivorRatio=percent命令来设置。
其次,可以看出,总大小total是从年龄为1的对象一直加过来的,直到加上某个年龄对象后total超过设定的比例。最后的result则是返回的真实threshold。

一句话来说,在hotspot中,当survivor中年龄小于等于age的对象占比超过TargetSurvivorRatio时,则年龄大于age的对象会直接晋升到老年代。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值