作者簡介:大家好,我是smart哥,前中興通訊、美團(tuán)架構(gòu)師,現(xiàn)某互聯(lián)網(wǎng)公司CTO
聯(lián)系qq:184480602,加我進(jìn)群,大家一起學(xué)習(xí),一起進(jìn)步,一起對抗互聯(lián)網(wǎng)寒冬
學(xué)習(xí)必須往深處挖,挖的越深,基礎(chǔ)越扎實!
階段1、深入多線程
階段2、深入多線程設(shè)計模式
階段3、深入juc源碼解析
階段4、深入jdk其余源碼解析
階段5、深入jvm源碼解析
一、簡介
本章,我們先來對系統(tǒng)運行過程中可能會遇到的各種JVM性能問題作個概述,以此為引子,作為后續(xù)實戰(zhàn)篇的鋪墊。
JVM性能優(yōu)化其實就是針對JVM內(nèi)存分配、參數(shù)設(shè)置進(jìn)行優(yōu)化,目的是減少GC次數(shù),避免對象頻繁進(jìn)入老年代。所以,我們來先來回顧下新生代和老年代的垃圾回收過程,并看下可能會引發(fā)的各種JVM性能問題。
在正式開始之前,我先給出一份JVM調(diào)優(yōu)模板,這份模板基本上涵蓋了JVM調(diào)優(yōu)所需的所有核心參數(shù),后續(xù)我們所有的調(diào)優(yōu)也會圍繞它展開:-Xms4096M -Xmx4096M -Xmn3072M -Xss1M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=256M -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFaction=92 -XX:UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:CMSParallellInitialMarkEnabled -XX:CMSScavengeBeforeRemark -XX:DisableExplicitGC -XX:PrintGCDetail -Xloggc:gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath:/usr/local/app/oom.hprof
上述有些參數(shù)看不懂沒關(guān)系,我們在后續(xù)的各個實戰(zhàn)章節(jié)中都會陸續(xù)提到,這里先簡要說下:
首先,JVM中各塊內(nèi)存區(qū)域大小的分配是根據(jù)系統(tǒng)運行模型來配置的,然后是ParNew和CMS這兩種垃圾回收器的配置,特別注意CMS的一些參數(shù),主要是提升CMS的效率和性能,還有就是打印GC日志,日志可以借助后續(xù)章節(jié)會講到的jstat工具進(jìn)行分析,最后兩個參數(shù)是在發(fā)生內(nèi)存溢出異常時,自動dump出內(nèi)存快照,然后就可以通過MAT等工具進(jìn)行分析了。
二、JVM性能問題
JVM運行時,最核心的區(qū)域就是Java堆內(nèi)存,這里會存放我們系統(tǒng)創(chuàng)建出來的各種對象。而且堆內(nèi)存通常劃分為新生代和老年代,新生代存放新創(chuàng)建出來的各種對象。所以,我們先來看下新生代GC會有哪些問題。
2.1 新生代GC
隨著系統(tǒng)的不斷運行,新生代中的對象會越來越多,直到快被塞滿。此時會根據(jù)GC Roots去尋找存活的對象。GC Roots一般是類靜態(tài)變量或方法的局部變量。由于我們創(chuàng)建對象最多的地方是在方法內(nèi),方法運行完畢,局部變量就沒有了,所以新生代中這種對象其實占了99%,這也是新生代對象存活率低的原因。
新生代進(jìn)行Minor GC時,會采用?復(fù)制算法?,將Eden區(qū)和一塊Survivor區(qū)的存活對象復(fù)制到另一塊Survivor區(qū),然后清空Eden和之前的Survivor。同時,新生代GC期間會”Stop the World“,即只允許GC線程進(jìn)行回收工作,其它工作線程都會被掛起。
假設(shè)一次新生代的GC需要20ms,那么此時對于用戶發(fā)送的請求,這20ms內(nèi)是無法處理的,系統(tǒng)會卡頓20ms。但是新生代的GC速度非???,所以只要不頻繁GC,其實對系統(tǒng)是沒什么影響的。所以,新生代GC其實沒什么好調(diào)優(yōu)的,只要多分配點堆內(nèi)存,保證Survivor區(qū)空間充足,那么低峰時期一般幾小時才有一次新生代GC,高峰期也最多幾分鐘一次新生代GC。
那么,什么時候新生代GC會對系統(tǒng)產(chǎn)生很大的影響呢?
當(dāng)系統(tǒng)部署在大內(nèi)存機器上時,比如32核64G的機器,新生代的Eden區(qū)可能有32G以上的內(nèi)存。
此時,如果系統(tǒng)的負(fù)載特別高(比如部署了Kafka、Elasticsearch每秒處理上萬的請求),那么可能導(dǎo)致Eden區(qū)的幾十G空間在短短幾分鐘內(nèi)被塞滿。而此時進(jìn)行新生代GC會停止系統(tǒng)的運行,由于新生代空間非常大,GC時間會很長,可能長達(dá)數(shù)秒鐘。
對于一個高負(fù)載高并發(fā)的系統(tǒng),每隔幾分鐘就停頓幾秒去進(jìn)行新生代GC,是不可接受的。
解決方案一般就是使用G1垃圾回收器,因為G1可以設(shè)置一個預(yù)期停頓時間(比如20ms),那么G1基于它的Region內(nèi)存劃分原理,就可以在運行一段時間之后,回收一部分Region,控制時間在20ms內(nèi),然后再運行再回收。
所以,?G1天生就適合在這種大內(nèi)存的機器上運行,可以完美解決大內(nèi)存垃圾回收時間過長的問題。
2.2 老年代GC
之前給大家講過新生代中對象晉升到老年代的幾個可能條件:
- 年齡太大
- 符合動態(tài)年齡判斷規(guī)則
- 大對象
- 新生代GC后存活的對象放不下Survivor區(qū)
上述條件中,關(guān)鍵是動態(tài)年齡判斷和對象放不下Survivor區(qū),從而導(dǎo)致大量對象頻繁進(jìn)入老年代:
老年代GC非常耗時,無論是CMS還是G1。通常老年代GC要比新生代GC慢十倍以上,所以針對老年代GC的優(yōu)化還是要先從新生代GC入手,合理分配內(nèi)存和設(shè)置JVM參數(shù),盡量讓對象不要頻繁進(jìn)入老年代。
三、各種GC分類
在基礎(chǔ)篇,我們介紹過各種GC類型,Minor GC、Full GC、Mixed GC、Young GC等等。本節(jié)我們就來統(tǒng)一梳理下。
3.1 Minor GC/Young GC
當(dāng)新生代的Eden區(qū)域被占滿后,實際就需要觸發(fā)新生代的GC,這就是所謂的”Minor GC“,也可以稱之為”Young GC“。后續(xù)章節(jié),我們統(tǒng)一用Young GC指代新生代的GC。
觸發(fā)時機:?新生代的Eden區(qū)域被占滿后。
3.2 Full GC/Old GC
Old GC是僅僅針對老年代區(qū)域進(jìn)行垃圾回收。而Full GC則是針對新生代、老年代、永久代的全體內(nèi)存空間進(jìn)行垃圾回收。后續(xù)章節(jié),我們統(tǒng)一用Old GC指代老生代的GC。
觸發(fā)時機:?老年代空間不夠。具體時機可細(xì)分為以下幾種:
- 進(jìn)行Young GC之前:如果老年代的連續(xù)可用內(nèi)存空間 < 新生代歷次晉升的平均大小,此時先觸發(fā)一次Old GC清理老年代,然后再執(zhí)行Young GC。
- 進(jìn)行Young GC之后:如果存活對象要進(jìn)入老年代,但是老年代的連續(xù)可用內(nèi)存空間 < 存放對象的大小,此時必須觸發(fā)一次Old GC。
- 老年代的內(nèi)存使用率超過了92%,此時也會觸發(fā)Old GC。
在很多JVM的實現(xiàn)機制里,當(dāng)上述幾種條件達(dá)到時,實際觸發(fā)的其實是Full GC,這個Full GC會包含Young GC、Old GC和永久代GC。
3.3 Mixed GC
Mixed GC是G1垃圾回收器中特有的概念,在G1中,一旦老年代占據(jù)了Java堆內(nèi)存的45%,就會觸發(fā)Mixed GC,此時對新生代和老年代都進(jìn)行垃圾回收。
觸發(fā)時機:?G1特有,老年代空間占據(jù)到Java堆內(nèi)存的45%。文章來源:http://www.zghlxwxcb.cn/news/detail-801281.html
3.4 永久代GC
永久代一般存放著類信息、常量池等等。在進(jìn)行Full GC的時候,會順帶對永久代進(jìn)行GC,一般來說永久代里的東西是不需要回收的,如果永久代真的滿了,回收之后也沒騰出足夠的空間來,就會拋出OOM異常。文章來源地址http://www.zghlxwxcb.cn/news/detail-801281.html
到了這里,關(guān)于JVM實戰(zhàn)(13)——JVM優(yōu)化概述的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!