當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]簡(jiǎn)介 JVM的參數(shù)有很多很多,根據(jù)我的統(tǒng)計(jì)JDK8中JVM的參數(shù)總共有1853個(gè),正式的參數(shù)也有680個(gè)。 這么多參數(shù)帶給我們的是對(duì)JVM的細(xì)粒度的控制,但是并不是所有的參數(shù)都需要我們自己去調(diào)節(jié)的,我們需要關(guān)注的是一些最常用的,對(duì)性能影響比較大的GC參數(shù)即可。 為了


簡(jiǎn)介


JVM的參數(shù)有很多很多,根據(jù)我的統(tǒng)計(jì)JDK8中JVM的參數(shù)總共有1853個(gè),正式的參數(shù)也有680個(gè)。


這么多參數(shù)帶給我們的是對(duì)JVM的細(xì)粒度的控制,但是并不是所有的參數(shù)都需要我們自己去調(diào)節(jié)的,我們需要關(guān)注的是一些最常用的,對(duì)性能影響比較大的GC參數(shù)即可。


為了更好的讓大家理解JDK8中 GC的調(diào)優(yōu)的秘籍,這里特意準(zhǔn)備了八張圖。在本文的最后,還附帶了一個(gè)總結(jié)的PDF all in one文檔,大家把PDF下載回去,遇到問(wèn)題就看兩眼,不美嗎?



分代垃圾回收器的內(nèi)存結(jié)構(gòu)


為了更好的提升GC的效率,現(xiàn)代的JVM都是采用的分代垃圾回收的策略(ZGC不是)。

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


java運(yùn)行時(shí)內(nèi)存可以分為JVM內(nèi)存和非JVM內(nèi)存。


JVM內(nèi)存又可以分為堆內(nèi)存和非堆內(nèi)存。


堆內(nèi)存大家都很熟悉了,YoungGen中的Eden,Survivor和OldGen。


非堆內(nèi)存中存儲(chǔ)的有thread Stack,Code Cache, NIO Direct Buffers,Metaspace等。


注意這里的Metaspace元空間是方法區(qū)在JDK8的實(shí)現(xiàn),它是在本地內(nèi)存中分配的。



JDK8中可用的GC


JDK8中到底有哪些可以使用的GC呢?


這里我們以HotSpot JVM為例,總共可以使用4大GC方式:

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


其中對(duì)于ParallelGC和CMS GC又可以對(duì)年輕代和老年代分別設(shè)置GC方式。


大家看到上圖可能有一個(gè)疑問(wèn),Parallel scavenge和Parallel有什么區(qū)別呢?


其實(shí)這兩個(gè)GC的算法是類(lèi)似的,Parallel Scavenge收集器也經(jīng)常稱為“吞吐量?jī)?yōu)先”收集器,Parallel Scavenge收集器提供了兩個(gè)參數(shù)用于精確控制吞吐量; -XX:MaxGCPauseMillis:控制最大垃圾收集停頓時(shí)間; -XX:GCTimeRatio:設(shè)置吞吐量大小。


同時(shí)Parallel Scavenge收集器能夠配合自適應(yīng)調(diào)節(jié)策略,把內(nèi)存管理的調(diào)優(yōu)任務(wù)交給虛擬機(jī)去完成。

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!

JDK8中默認(rèn)開(kāi)啟的是ParallelGC。

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


打印GC信息


如果想研究和理解GC的內(nèi)部信息,GC信息打印是少不了的:

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


上圖提供了一些非常有用的GC日志的控制參數(shù)。



內(nèi)存調(diào)整參數(shù)


JVM分為Heap區(qū)和非Heap區(qū),各個(gè)區(qū)又有更細(xì)的劃分,下面就是調(diào)整各個(gè)區(qū)域大小的參數(shù):

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!




Thread配置


TLAB大家還記得嗎?


如果一個(gè)對(duì)象的分配是在方法內(nèi)部,并且沒(méi)有多線程訪問(wèn)的情況下,那么這個(gè)對(duì)象其實(shí)可以看做是一個(gè)本地對(duì)象,這樣的對(duì)象不管創(chuàng)建在哪里都只對(duì)本線程中的本方法可見(jiàn),因此可以直接分配在??臻g中。


棧上分配的對(duì)象因?yàn)椴挥每紤]同步,所以執(zhí)行速度肯定會(huì)更加快速,這也是為什么JVM會(huì)引入棧上分配的原因。

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


上圖就是TLAB的參數(shù)。



通用GC參數(shù)


雖然JDK8的GC這么多,但是他們有一些通用的GC參數(shù):

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


這里講解一下Young space tenuring,怎么翻譯我不是很清楚,這個(gè)主要就是指Young space中的對(duì)象經(jīng)過(guò)多少次GC之后會(huì)被提升到Old space中。



CMS GC


CMS全稱是Concurrent mark sweep。是一個(gè)非常非常復(fù)雜的GC。


復(fù)雜到什么程度呢?光光是CMS調(diào)優(yōu)的參數(shù)都有一百多個(gè)!


下圖是常用的CMS的參數(shù)。

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!


CMS這里就不多講了,因?yàn)樵贘DK9之后,CMS就已經(jīng)被廢棄了。


主要原因是CMS太過(guò)復(fù)雜,如果要向下兼容需要巨大的工作量,然后就直接被廢棄了。


在JDK9之后,默認(rèn)的GC是G1。



G1參數(shù)


G1收集器是分代的和region化的,也就是整個(gè)堆內(nèi)存被分為一系列大小相等的region。在啟動(dòng)時(shí),JVM設(shè)置region的大小,根據(jù)堆大小的不同,region的大小可以在1MB到32MB之間變動(dòng),region的數(shù)量最多不超過(guò)2048個(gè)。Eden區(qū)、Survivor區(qū)、老年代是這些region的邏輯集合,它們并不是連續(xù)的。


G1中的垃圾收集過(guò)程:年輕代收集和混合收集交替進(jìn)行,背后有全局的并發(fā)標(biāo)記周期在進(jìn)行。


當(dāng)老年代分區(qū)占用的空間達(dá)到或超過(guò)初始閾值,就會(huì)觸發(fā)并發(fā)標(biāo)記周期。


下圖是G1的調(diào)優(yōu)參數(shù):

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒(méi)關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!

長(zhǎng)按訂閱更多精彩▼

八張圖徹底了解JDK8 GC調(diào)優(yōu)秘籍!

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉