JVM新生代、老年代的默認(rèn)比值真的是1:2嗎?
原創(chuàng)圖片來自 Pexels
【51CTO.com原創(chuàng)稿件】業(yè)界的普遍認(rèn)知如下圖所示,正確嗎?
結(jié)論先行:如果你啟動(dòng)進(jìn)程時(shí)未添加任何 JVM 調(diào)優(yōu)參數(shù),也就是說完全默認(rèn)選項(xiàng),那么無論你用的是哪個(gè) JDK 版本,新生代、老年代的默認(rèn)比值早就不是 1:2 了!
Eden、Survivor From、Survivor To 的默認(rèn)比值也早就不是 8:1:1 了!理由慢慢道來。
01先說 JDK 版本
從 JDK1.5 開始,公開版本號(hào)改為 JDK5 的命令方式,只有開發(fā)版本號(hào)才沿用 JDK1.5 的命令方式。
截止目前,最新的 JDK 版本是 2021 年 3 月份發(fā)布的 JDK16,本文闡述的范圍將囊括所有的 JDK 版本,但是以 JDK8 為主線,因?yàn)?JDK8 目前的市場(chǎng)占有率仍然最高,并且 JDK8 屬于 LTS 版本(Long Term Support,長(zhǎng)期支持)。
JDK8 于 2014 年 3 月發(fā)布,JDK8 承諾的最后支持日期是:2030 年 12 月。
JDK8 之后的下一個(gè) LTS 版本是于 2018 年 9 月發(fā)布的 JDK11,JDK11 承諾的最后支持日期是:2026 年 9 月,尚不如 JDK8 支持的時(shí)間久。
再下一個(gè) LTS 版本是將于 2021 年 9 月發(fā)布的 JDK17。JDK 的版本發(fā)布,從 JDK9 開始改為嚴(yán)格基于時(shí)間的模式,固定每半年推出 1 個(gè)新版本,每 3 年推出 1 個(gè) LTS 版本。
02再說 GC 回收器
說明如下:
①根據(jù) JDK 最新版本,除上面提到的 9 個(gè) GC 回收器外,還有 1 個(gè)是 JDK11 引入的 Epsilon 回收器。
也就是說歷史至今,目前一共有 10 個(gè) GC 回收器,Epsilon 回收器不執(zhí)行任何垃圾回收的工作(A No-Op Garbage Collector)。
比如針對(duì)如性能測(cè)試等期望排除 GC 性能影響且進(jìn)程執(zhí)行生命周期較短的特別場(chǎng)景。所以不在本文的討論范疇內(nèi)。
②ZGC 和 Shenandoah 的設(shè)計(jì)目標(biāo)類似,均為針對(duì) G1 的不足。唯獨(dú) ZGC 由 Oracle 公司發(fā)起,Shenandoah 由 RedHat 公司發(fā)起,所以官方重視程度會(huì)有些許差異。
另外,直到 JDK16,這 2 個(gè)回收器仍然未取代 G1 成為默認(rèn)選項(xiàng)。盡管官宣這 2 個(gè)回收器可兼顧吞吐量和響應(yīng)時(shí)間,但每個(gè) JDK 版本都在持續(xù)優(yōu)化,尚未達(dá)到成熟。
③-XX:+UseParNewGC 的組合已在 JDK8 的“JEP 173: Retire Some Rarely-Used GC Combinations”廢棄。詳見:http://openjdk.java.net/jeps/173。
原因是:很少使用的組合。
④-XX:+UseConcMarkSweepGC 的組合中的 CMS 回收器已在 JDK9 的“JEP 291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector”不再建議使用。
并且已在 JDK14 的“JEP 363: Remove the Concurrent Mark Sweep (CMS) Garbage Collector”廢棄。
詳見:http://openjdk.java.net/jeps/291、http://openjdk.java.net/jeps/363。
原因是:G1 已成為默認(rèn)回收器,G1 同 CMS 一樣是響應(yīng)時(shí)間優(yōu)先,G1 使命就是替換掉 CMS。
每個(gè) GC 回收器具體的功能和原理,由于篇幅有限,本文就不做細(xì)節(jié)的闡述。
03新生代、老年代的默認(rèn)比值由哪個(gè)參數(shù)決定
NewRatio,默認(rèn)值:2,也就是說新生代和老年代的默認(rèn)比值是 1:2。
如下圖所示,不僅 JDK8 的 NewRatio 默認(rèn)值是 2,最新版 JDK16 的 NewRatio 默認(rèn)值仍然也是 2。SurvivorRatio,默認(rèn)值:8,效果同。
盡管 NewRatio 和 SurvivorRatio 的默認(rèn)值是沒有問題的,但是未必實(shí)際生效,下面將闡述具體的驗(yàn)證分析過程。
04驗(yàn)證分析
以下驗(yàn)證分析過程均基于 JDK8。
①啟動(dòng)進(jìn)程時(shí)不添加任何 JVM 參數(shù)
默認(rèn):-XX:+UseParallelGC,Parallel Scavenge+Parallel Old 的 GC 回收器組合。
如下圖,的確 NewRatio=2,并且 NewSize=42.0MB,OldSize=84.0MB,符合 1:2。
但是看 Heap Usage 詳情,Eden Space capacity=306.5MB,相比 PS Old Generation capacity=130.5MB 還要更多呢。
另外 Eden、Survivor From、Survivor To 的比值也明顯不是 8:1:1,為什么會(huì)這樣?
②改用其他 GC 回收器的參數(shù)試試?
-XX:+UseSerialGC:Serial+Serial Old 的 GC 回收器組合。
看 Heap Usage 詳情,多了一塊 New Generation=Eden+1 Survivor Space。
如果再加上另外 1 個(gè) Survivor Space(From Space 或者 To Space),剛好是 42.0MB,同 OldSize 的比值是 1:2,沒有任何問題。
另外,Eden、Survivor From、Survivor To 的比值也明顯是 8:1:1。
-XX:+UseConcMarkSweepGC:ParNew+CMS 的 GC 回收器組合。
看 Heap Usage 詳情,效果與 -XX:+UseSerialGC 基本一致,也沒問題。
-XX:+UseG1GC:G1 回收器。
看 Heap Usage 詳情,也不合符 NewRatio 標(biāo)識(shí)的 1:2 的默認(rèn)比值。另外 From Space 和 To Space 也消失了,為什么會(huì)這樣?
其他組合:要么被 Deprecate,要么被 Remove,就不做參考了。
③原因分析
(1)在 JDK 1.3 及之前,-XX:+UseSerialGC 是回收器的唯一選擇。當(dāng)時(shí)來說,JVM 新生代、老年代的默認(rèn)比值的的確確是 1:2。
(2)-XX:+UseConcMarkSweepGC 類似于 -XX:+UseSerialGC 的多線程版本,并且有代碼框架的復(fù)用,所以表現(xiàn)一樣。
(3)-XX:+UseSerialGC、-XX:+UseG1GC、-XX:+UseZGC、-XX:+UseShenandoahGC,都沒有使用傳統(tǒng)的 GC 代碼框架,所以表現(xiàn)不一樣。
(4) 基于上一點(diǎn),值得注意的是 JDK7U4 之前 -XX:+UseParallelGC 的老年代 GC 是 Serial Old。
其實(shí)也并沒有復(fù)用 Serial Old 的代碼框架,-XX:+UseParallelGC 的老年代 GC 叫:PS MarkSweep,其實(shí)現(xiàn)原理與 Serial Old 非常接近,所以包括官方在內(nèi)的許多資料統(tǒng)一用 Serial Old 來稱呼而已。
(5) UseAdaptiveSizePolicy 參數(shù),非常重要!該參數(shù)默認(rèn)開啟,直到最新版 JDK16 仍然開啟。
該參數(shù)對(duì) -XX:+UseSerialGC 和 -XX:+UseConcMarkSweepGC 無論開啟與否,均不生效。
該參數(shù)對(duì)應(yīng)的是 GC 自適應(yīng)的調(diào)節(jié)策略(GC Ergonomics),如果開啟,那么 JVM 會(huì)根據(jù)系統(tǒng)的運(yùn)行情況,動(dòng)態(tài)調(diào)整一些參數(shù),包括:新生代和老年代的比值。
Eden、Survivor From、Survivor To 的比值;大對(duì)象直接進(jìn)入老年代的閾值等,以達(dá)到吞吐量?jī)?yōu)先的目標(biāo)。
④關(guān)閉 UseAdaptiveSizePolicy 參數(shù)試試?
開啟參數(shù)是在 -XX 后面帶加號(hào),關(guān)閉參數(shù)是在 -XX 后面帶減號(hào)。啟動(dòng)進(jìn)程時(shí)候添加 JVM 參數(shù) -XX:-UseAdaptiveSizePolicy。
GC 回收器仍然保持默認(rèn):-XX:+UseSerialGC,Parallel Scavenge+Parallel Old 的組合。
查看 Heap Usage 詳情,一切正常了,新生代、老年代的比值是 1:2。Eden、Survivor From、Survivor To 的比值也是 8:1:1。
⑤UseAdaptiveSizePolicy 參數(shù)相關(guān)源碼分析
從 http://hg.openjdk.java.net 獲取 hotspot 的源碼。
-XX:+UseParallelGC 的新生代實(shí)現(xiàn)在 psScavenge.cpp,老年代實(shí)現(xiàn)在 psOldGen.cpp,均在 hotspot\src\share\vm\gc_implementation\parallelScavenge 目錄下。
如下圖,當(dāng) UseAdaptiveSizePolicy 默認(rèn)開啟,那么進(jìn)入動(dòng)態(tài)調(diào)整的處理邏輯。
如下圖,是進(jìn)入動(dòng)態(tài)調(diào)整的處理邏輯后的最核心代碼 heap→resize_young_gen。
⑥最新的 -XX:+UseZGC 或 -XX:+UseShenandoahGC 呢?
G1 回收器也是遵循分代收集理論的,但是會(huì)把連續(xù)的 Java 堆不區(qū)分新生代、老年代的情況下而劃分為大小相等的 Region,每個(gè) Region 都會(huì)根據(jù)需要扮演新生代或老年代的空間。
G1 仍然保留了新生代、老年代,并且新生代也區(qū)分 Eden 和 Survivor,只是 Survivor 不再區(qū)分 From 和 To。
而 ZGC 和 ShenandoahGC 的話,顛覆的比較徹底,已經(jīng)不再區(qū)分新生代和老年代了,也就是說不再使用分代收集,默認(rèn)比值多少的問題已經(jīng)沒有意義了。
05結(jié)論
①NewRatio,默認(rèn)值是 2,這個(gè)是亙古不變、千真萬確的,哪怕最新的 JDK16 版本仍然也是。
畢竟最最歷史悠久、居功至偉的 -XX:+UseSerialGC 始終既沒有被 Deprecate,也沒有被 Remove。目前依然是 Client 模式下的默認(rèn)選項(xiàng)。
②JVM 新生代、老年代的默認(rèn)比值跟選擇的 GC 回收器有關(guān)!不僅僅只是有關(guān),同時(shí)還決定著新生代、老年代的概念是否存在。
③從 -XX:+UseParallelGC 取代 -XX:+UseSerialGC 成為默選項(xiàng)起,JVM 新生代、老年代的默認(rèn)比值早已不再是 1:2 了,而是比值可被動(dòng)態(tài)調(diào)整,比如目前市場(chǎng)占有率最高的 JDK8。
④從 JDK9 開始,-XX:+UseG1GC 取代 -XX:+UseParallelGC 成為默認(rèn)選項(xiàng)。
或者是今后 -XX:+UseZGC 或 -XX:+UseShenandoahGC 可能成為默認(rèn)選項(xiàng)(畢竟設(shè)計(jì)目標(biāo)就是針對(duì) G1 的不足)。
JVM 新生代、老年代的默認(rèn)比值更不可能再是 1:2 了,就連新生代、老年代的概念都可能不存在了。
所以,JVM 新生代、老年代的默認(rèn)比值是 1:2 的錯(cuò)誤認(rèn)知,持續(xù)已有 10 年之久。
面試官和求職者在未經(jīng)考究的情況下總是“默契有佳”!期望通過本文可以改變行業(yè)的一些錯(cuò)誤認(rèn)知。
另外,縱使被業(yè)界奉為:JVM 葵花寶典寶典 & 資深 JVM 教科書級(jí)別的《深入理解 Java 虛擬機(jī)》,書中不少論點(diǎn)也并未及時(shí)得到更新,可能會(huì)對(duì)讀者產(chǎn)生一些的誤導(dǎo)。
盡信書不如無書,拿死記硬背的面試題去糊弄求職者的面試官就是耍流氓。
作者:大黃蜂
簡(jiǎn)介:曾就職于華為、騰訊等大型互聯(lián)網(wǎng)公司,于 2018 年 5 月加盟獨(dú)角獸公司 akulaku 擔(dān)任技術(shù)管理職務(wù),對(duì)分期、金融借貸等核心系統(tǒng)的架構(gòu)設(shè)計(jì)具有豐富的實(shí)戰(zhàn)經(jīng)驗(yàn)。精通 Redis 和 JVM,非常重視底層原理,對(duì)高級(jí)用法、協(xié)議、源碼等具有深入的研究。并且,具有自己獨(dú)特的團(tuán)隊(duì)管理理念,另辟蹊徑,專注研發(fā)質(zhì)量和效率,為公司培養(yǎng)出多名青年高潛,并多次榮獲各類表彰。
編輯:陶家龍
征稿:有投稿、尋求報(bào)道意向技術(shù)人請(qǐng)?zhí)砑有【幬⑿?gordonlonglong
【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】