JVM誤區--動態對象年齡判定


《深入理解Java虛擬機》中有如上的一段描述,講的是動態對象年齡判定,避免-XX:MaxTenuringThreshold 設置過大導致大量對象無法晉升。
但是存在一個問題,如果說非得相同年齡所有對象大小總和大於Survivor空間的一半才能晉升,按照如下場景:
  1. MaxTenuringThreshold為15
  2. 年齡1的對象占用了33%
  3. 年齡2的對象占用33%
  4. 年齡3的對象占用34%。

得出推論:

  1. 按照晉升的標准。首先年齡不滿足MaxTenuringThreshold,不會晉升。
  2. 每個年齡的對象都不滿足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的值。

# 目標存活率,默認為50%
-XX:TargetSurvivorRatio

根據代碼可以看到,動態年齡計算方式為:

  1. 通過這個比率來計算一個期望值,desired_survivor_size 。
  2. 然后用一個total計數器,累加每個年齡段對象大小的總和。
  3. 當total大於desired_survivor_size 停止。
  4. 然后用當前age和MaxTenuringThreshold 對比找出最小值作為結果。

總體表征就是,年齡從小到大進行累加,當加入某個年齡段后,累加和超過survivor區域*TargetSurvivorRatio的時候,就從這個年齡段網上的年齡的對象進行晉升。

所以上面的場景,年齡1的占用了33%,年齡2的占用了33%,累加和超過默認的TargetSurvivorRatio(50%),年齡2和年齡3的對象都要晉升。

動態對象年齡判斷,主要是被TargetSurvivorRatio這個參數來控制。而且算的是年齡從小到大的累加和,而不是某個年齡段對象的大小。

 
參考:
《深入理解Java虛擬機》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM