1. JVM內(nèi)存結(jié)構(gòu)
1.1 運行時數(shù)據(jù)區(qū)
程序計數(shù)器PC Register:JVM支持多線程同時執(zhí)行,每一個線程都有自己的PC Register,線程正在執(zhí)行的方法叫做當前方法,如果是java代碼,PC Register里面存放的就是房錢正在執(zhí)行的指令的地址,如果你是C代碼审孽,則為空。
Java虛擬機棧(Java Virtual Machine Stacks)是線程私有的浑娜,它的生命周期與線程相同佑力。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀,用于存儲局部變量表棚愤、操作數(shù)棧搓萧、動態(tài)鏈接、方法出口燈信息宛畦。每一個方法從調(diào)用直至執(zhí)行完成的過程瘸洛,就對應(yīng)著一個棧幀在虛擬機棧中入棧到出棧的過程。
Java堆(Java Heap)是Java虛擬機所管理的內(nèi)存中最大的一塊次和。堆是被所有線程共享的一塊內(nèi)存區(qū)域反肋,在虛擬機啟動時創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對象實例踏施,幾乎所有的對象實例都在這里分配內(nèi)存石蔗。Java堆可以處于物理上不連續(xù)的內(nèi)存空間中,只要邏輯上是連續(xù)的即可畅形。
方法區(qū)(Method Area):方法區(qū)域java堆一樣养距,是各個線程共享的內(nèi)存區(qū)域,它用于存儲已被虛擬機加載的類信息日熬、常亮棍厌、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。雖然Java虛擬機規(guī)范把方法區(qū)描述為堆的一個邏輯部分耘纱,但是它卻有一個別名叫做Non-Heap(非堆)敬肚,目的是與Java堆區(qū)分開來。
運行時常量池(Runtime Constant Pool)是方法區(qū)的一部分束析。Class文件中除了有類的版本艳馒、字段、方法员寇、接口等描述信息外弄慰,還有一項信息是常量池(Constant Pool Table),用于存放編譯器生成的各種字面量和符號引用丁恭,這部分內(nèi)容將在類加載后進入方法區(qū)的常量池中存放曹动。
本地方法棧(Native Method Stacks)與虛擬機棧所放回的作用是非常相似的,它們之間的區(qū)別不過是虛擬機棧為虛擬機執(zhí)行的Java方法(也就是字節(jié)碼)服務(wù)牲览,而本地方法棧則為虛擬機使用到的Native方法服務(wù)。
1.2 JVM的內(nèi)存結(jié)構(gòu)
實例:
啟用壓縮類空間:
jstat -gc 13144
禁用壓縮類空間:
jstat -gc 13523
codecache也是一樣操作恶守。
-xint
常用參數(shù):
-Xms-Xmx
-XX:NewSize -XX:MaxNewSize
-XX:NewRatio -XX:SurvivorRatio
-XX:MetaspaceSize -XX:MaxMetaspaceSize
-XX:+UseCompressedClassPointers
-XX:CompressedClassSpaceSize
-XX:InitialCodeCacheSize
-XX:ReservedCodeCacheSize
2. 垃圾回收算法
2.1 如何確定垃圾
2.2 各類算法
對象分配:
對象優(yōu)先分配在Eden區(qū)第献。
大對象直接進入老年代:-XX:PretenureSizeThreshold,該參數(shù)規(guī)定多大的對象會直接分配在老年代兔港。
長期存活對象進入老年代:?
-XX:MaxTenuringThreshold 晉升閾值?
-XX:+PrintTenuringDistribution 發(fā)生Young GC時候庸毫,打印存活對象的年齡的分布情況?
-XX:TargetSurivorRatio 設(shè)置Surivor區(qū),Young區(qū)垃圾回收后存活對象的比例衫樊,假設(shè)該值設(shè)置為80%飒赃,意味著發(fā)生一次Young GC,Surivor區(qū)存活對象為80%科侈,這時候需要計算這些80%存活對象的平均年齡载佳,用平均年齡和晉升閾值之間取一個最小值,如果有對象年齡大于該最小值臀栈,也會將該對象晉升到老年代蔫慧。
3. 垃圾收集器
3.1 三種類型垃圾收集器
串行收集器Serial:Serial、Serial Old权薯。單線程姑躲,適用于內(nèi)存小的嵌入式設(shè)備。
并行收集器Parallel:Paralel Scavenge盟蚣、Parallel Old黍析,吞吐量優(yōu)先。
并發(fā)收集器Concurrent:CMS屎开、G1阐枣,停頓時間優(yōu)先。
3.2 并行VS并發(fā)
并行是指多條垃圾收緊線程并行工作,但此時用戶線程仍然處于等待狀態(tài)侮繁。適合科學計算虑粥、后臺處理等弱交互場景。
并發(fā)指用戶線程與垃圾收集線程同時執(zhí)行(但不一定是并行的宪哩,可能會交替執(zhí)行)娩贷,垃圾收集線程在執(zhí)行的時候不會停頓用戶程序的運行。適合對響應(yīng)時間有要求的場景锁孟,比如Web彬祖。
3.3 停頓時間VS吞吐量
停頓時間:垃圾收集器做垃圾回收中斷應(yīng)用執(zhí)行的時間,-XX:MaxGCPauseMillis
吞吐量:花在垃圾收集的時間和花在應(yīng)用時間的占比品抽。-XXGCTimeRatio=<n>储笑,來及收集時間占:1/1+n。
3.4 如何評價一個垃圾回收器的好壞
3.5 三種類型垃圾收集器開啟與停用
串行收集器:
并行收集器:
并發(fā)收集器:
3.6 垃圾收集器搭配
有連線的是可以相互搭配使用圆恤。
JDK8推薦使用G1突倍,性能比較好,在Yong區(qū)和Old區(qū)都可以使用盆昙。
虛線表示CMS可能退化成SerialOld羽历,空間擔保分配失敗。
如何選擇垃圾收集器淡喜?
優(yōu)先調(diào)整堆的大小秕磷,讓JVM自己來選擇;
如果內(nèi)存小于100M炼团,使用串行收集器澎嚣;
如果是單核,并沒有停頓時間的要求瘟芝,串行或JVM自己選易桃;
如果允許停頓時間超過1秒,選擇并行或JVM自己選模狭;
如果響應(yīng)時間非常重要颈抚,并且不能超過1秒,使用并發(fā)收集器嚼鹉;
3.7 兩種常用垃圾收集器
3.7.1 Parallel Collector
工作原理:當發(fā)現(xiàn)內(nèi)存不夠時贩汉,暫停應(yīng)用程序,啟動多個垃圾回收線程來回收垃圾锚赤,垃圾回收結(jié)束后匹舞,重新啟動應(yīng)用程序。
-XX:+UseParallelGC 手動開啟线脚,server模式默認開啟赐稽;
-XX:ParallelGCThreads=<n> 開啟多少個GC線程叫榕;
并行收集器的自適應(yīng)特性(Parallel Collector Ergonomics),會自動調(diào)整堆得大小姊舵,來自適應(yīng)調(diào)整滿足我們設(shè)定的指標:
-XX:MaxGCPauseMills=<n> 最大停頓時間晰绎;
-XX:GCTimeRatio=<n> 吞吐量;
-Xmx 堆的大欣ǘ 荞下;?
優(yōu)先滿足停頓時間要求,然后滿足吞吐量要求史飞,如果兩個都滿足的話尖昏,它會減小堆得大小,來滿足停頓時間的要求构资,直到這三個條件中有一個是滿足不了的抽诉。自適應(yīng)其實不是最優(yōu)的,因為它需要動態(tài)調(diào)整堆得大小來滿足這些條件吐绵。?
動態(tài)內(nèi)存調(diào)整?
并行收集器在自適應(yīng)的時候會動態(tài)調(diào)整內(nèi)存迹淌;
-XX:YongGenerationSizeIncrement=<Y> Yong區(qū)動態(tài)調(diào)整每次增加的大小,默認20%拦赠;
-XX:TenuredGenerationSizeIncrement=<T> Old區(qū)動態(tài)調(diào)整每次增加的大小巍沙,默認20%;
-XX:AdaptiveSizeDecrementScaleFactor= 動態(tài)減小時每次減小的大小荷鼠,默認4%;?
在生產(chǎn)環(huán)境下很少使用自適應(yīng)功能榔幸,主要通過手動調(diào)整允乐。
3.7.2 CMS Collector
(1)CMS垃圾收集過程
由于篇幅限制原因,更多關(guān)于jvm知識點的學習思維導(dǎo)圖以及上面垃圾收集的高清大圖可以私信筆者“jvm”領(lǐng)取