虛擬機并不是永遠地要求對象的年齡必須達到了MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。
學習jvm的人,基本都閱讀過上面這段話,這里講的是動態年齡的判定。對于動態的判定的條件就是相同年齡所有對象大小的總和大于Survivor空間的一半,然后算出的年齡要和MaxTenuringThreshold的值進行比較,以此保證MaxTenuringThreshold設置太大(默認15),導致對象無法晉升。
問題的提出
場景假設
如果說非得相同年齡所有對象大小總和大于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這個參數來控制。而且算的是年齡從小到大的累加和,而不是某個年齡段對象的大小。看完后先記住這個參數吧TargetSurvivorRatio,雖然你以后基本不會調整他。