博客 / 詳情

返回

OpenJDK11推薦使用G1而不是ZGC的4個原因 - 知乎

OpenJDK11下,目前不建議使用ZGC,主推G1,主要是基於幾個考慮:

1)ZGC時Java進程佔用三倍內存問題:由於ZGC着色指針把內存空間映射了3個虛擬地址,使得TOP/PS等命令查看佔用內存時看到Java進程佔用內存過大。此問題不影響操作系統,但是會影響到監控運維工具,需要注意。。

參考以下材料:

  • ZGC最大堆大小超過物理內存:https://www.it1352.com/2281965.html
  • 英文原文:https://stackoverflow.com/questions/57899020/zgc-max-heap-size-exceed-physical-memory
  • 《ZGC設計與實現》書裏也有講過:https://gitee.com/laifengting/LFT-Note/blob/master/ZGC%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AE%9E%E7%8E%B0.md#221%E5%A4%9A%E8%A7%86%E5%9B%BE%E6%98%A0%E5%B0%84
  • Tencent Kona JDK11無暫停內存管理ZGC生產實踐裏也有提過:https://mp.weixin.qq.com/s/BH7XAuSs4QsseIK-gMeD7A

2)同樣的應用ZGC內存佔用會多一些

主要原因是ZGC借用了對象頭,導致無法使用指針壓縮功能。OpenJDK11+64位系統下,使用G1,默認UseCompressedOops是打開的,ZGC是false。不過內存夠的情況下,這個影響不大。因為對於小於32G的堆,壓縮oops能節省一部分內存,地址換算得多用一些CPU,同時只要垃圾能回收掉,都沒啥影響。https://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html

3)Metaspace區佔用內存過多問題

OpenJDK11下ZGC不能實現Class Unloading,加上本來也不能使用指針壓縮,所以內存佔用量比G1要大,這個問題在OpenJDK12-15陸續有多個補丁修復。KonaJDK/DragonwellJDK已經把相關的補丁都backport到KonaJDK11,所以不存在這方面的問題。KonaJDK參見上面鏈接。Dragonwell參見:https://developer.aliyun.com/article/789096

4)吞吐量低於G1 GC。一般來説,可能會下降5%-15%。對於堆越小,這個效應越明顯,堆非常大的時候,比如100G,其他GC可能一次Major或Full GC要幾十秒以上,但是對於ZGC不需要那麼大暫停。這種細粒度的優化帶來的副作用就是,把很多環節其他GC裏的STW整體處理,拆碎了,放到了更大時間範圍內裏去跟業務線程併發執行,甚至會直接讓業務線程幫忙做一些GC的操作,從而降低了業務線程的處理能力。

總結:在OpenJDK11版本,建議優先使用G1 GC。如果想使用ZGC,建議使用OpenJDK17版本,或者使用KonaJDK 11/Dragonwell JDK 11。

ZGC在JDK16+版本(特別是當前LTS 17),還是推薦可以用的,修復了各類問題。特別是當前ZGC是不分代的,可以預期在下一個LTS版本,引入了分代處理,ZGC可以把STW停頓降低到1ms以內。

btw:官方各種GC的調優建議:

https://docs.oracle.com/en/java/javase/11/gctuning/garbage-first-garbage-collector-tuning.html

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.