查看自己設(shè)置的jvm參數(shù)
java -XX:+PrintCommandLineFlags
idea日志
C:\Users\Lenovo\.IntelliJIdea2018.1\system\log
查看idea的參數(shù)配置 在help 里的custom vm options
# custom IntelliJ IDEA VM options
-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
jstat最杰出的功能便是監(jiān)控JVM進(jìn)行垃圾回收(GC)的相關(guān)信息
JVM學(xué)習(xí)之jstat使用方法 - 星星滿天 - 博客園
使用示例:jstat –gc –h3 6033 250 10
解釋:監(jiān)控gc的信息,每三行輸出一次表頭,監(jiān)控的進(jìn)程pid為6033,每250ms輸出一次信息瞒渠,一共輸出10次厅篓。
參數(shù)說明:
S0C: Survivor0(幸存區(qū)0)大懈氖纭(KB)
S1C: Survivor1(幸存區(qū)1)1大小(KB)
S0U: Survivor0(幸存區(qū)0)已使用大辛敉(KB)
S1U: Survivor1(幸存區(qū)1)已使用大胁右巍(KB)
EC? : Eden(伊甸區(qū))大惺庹摺(KB)
EU? : Eden(伊甸區(qū))已使用大泻拊鳌(KB)
OC :老年代大腥锿恕(KB)
OU : 老年代已使用大小(KB)
PC : Perm永久代大秀究摇(KB)
PU : Perm永久代已使用大腥坷蟆(KB)
YGC:新生代GC個數(shù)
YGCT:新生代GC的耗時(秒)
FGC? :Full GC次數(shù)
FGCT:Full GC耗時(秒)
GCT :GC總耗時(秒)
查看各個代的容量情況
jstat –-gccapacity –h3 6033 250 10
NGCMN:新生代最小值(KB)
NGVMX:新生代最大值(KB)
NGC:當(dāng)前新生代大小(KB)
S0C:同上
S1C:同上
EC:同上
OGCMN:老年代最小值(KB)
OGCMX:老年代最大值(KB)
OGC:當(dāng)前老年代大性孔椤(KB)
OC:同上
PGCMN:永久代最小值(KB)
PGCMX:永久代最大值(KB)
PGC:當(dāng)前永久代大惺湎酢(KB)
PC:同上
YGC:同上
FGC:同上
Jconsole使用
cmd ?中輸入 jconsole 就可以了 但后監(jiān)聽pid點(diǎn)擊確定
JVM的新生代、老年代程梦、MinorGC点把、MajorGC - Nutty - 博客園
新生代又分為 Eden區(qū)、ServivorFrom屿附、ServivorTo三個區(qū)郎逃。
ServivorTo:保留了一次MinorGC過程中的幸存者。
ServivorFrom:上一次GC的幸存者挺份,作為這一次GC的被掃描者褒翰。
MinorGC的過程:
MinorGC采用復(fù)制算法。首先匀泊,把Eden和ServivorFrom區(qū)域中存活的對象復(fù)制到ServicorTo區(qū)域(如果有對象的年齡以及達(dá)到了老年的標(biāo)準(zhǔn)优训,則賦值到老年代區(qū)),同時把這些對象的年齡+1(如果ServicorTo不夠位置了就放到老年區(qū))各聘;然后揣非,清空Eden和ServicorFrom中的對象;最后躲因,ServicorTo和ServicorFrom互換早敬,原ServicorTo成為下一次GC時的ServicorFrom區(qū)。
永久代
主要存放Class和Meta(元數(shù)據(jù))的信息,Class在被加載的時候被放入永久區(qū)域. 它和和存放實(shí)例的區(qū)域不同,GC不會在主程序運(yùn)行期對永久區(qū)域進(jìn)行清理毛仪。所以這也導(dǎo)致了永久代的區(qū)域會隨著加載的Class的增多而脹滿搁嗓,最終拋出OOM異常。? 在Java8中箱靴,永久代已經(jīng)被移除腺逛,被一個稱為“元數(shù)據(jù)區(qū)”(元空間)的區(qū)域所取代。類的元數(shù)據(jù)放入 native memory, 字符串池和類的靜態(tài)變量放入java堆中. 這樣可以加載多少類的元數(shù)據(jù)就不再由MaxPermSize控制, 而由系統(tǒng)的實(shí)際可用空間來控制.
JVM的組成(5)
方法區(qū)衡怀,java堆棍矛,虛擬機(jī)棧,本地方法區(qū)抛杨,程序計(jì)數(shù)器够委。
JAVA內(nèi)存區(qū)域與和區(qū)域OOM問題
?1:程序計(jì)數(shù)器
???? 當(dāng)前線程執(zhí)行的字節(jié)碼文件的行號指示器,用于線程切換之后恢復(fù)上次執(zhí)行時的位置繼續(xù)執(zhí)行怖现。各個線程之間的計(jì)數(shù)器互不影響茁帽,“線程私有”玉罐。
???? 這是唯一一個在JVM中沒有OOM異常的區(qū)域。
??? 2:虛擬機(jī)棧
???? 這也是線程私有的潘拨,保留了當(dāng)前線程的方法棧幀:每個方法執(zhí)行時會創(chuàng)建棧幀吊输,用于存儲局部變量、操作數(shù)铁追、方法出口等季蚂。每個方法從調(diào)用到執(zhí)行完成就對應(yīng)這一個棧幀在虛擬機(jī)棧中入棧到出棧的過程。
???? 這個區(qū)域有兩種異常:方法棧的深度大于虛擬機(jī)所允許的深度就會拋出StackOverflowError異常琅束;棧的大小擴(kuò)展時如果無法獲得足夠的內(nèi)存就會拋出OOM異常扭屁。
??? 3:本地方法棧
???? 為本地的Native方法服務(wù),功能與虛擬機(jī)棧類似涩禀,也會由于深度問題或擴(kuò)展時內(nèi)存不夠而拋出StackOverflowError或OOM異常料滥。
??? 4:Java堆
???? 被所有線程共享的一片區(qū)域,所有對象實(shí)例以及數(shù)組都在堆上分配內(nèi)存艾船♂E罚可以通過:-Xmx、-Xmx設(shè)置堆的大小上下限丽声。我們習(xí)慣上把堆劃分為新生代和老年代礁蔗,具體劃分在GC機(jī)制的博文詳述。
???? 當(dāng)堆的內(nèi)存不足時雁社,拋出OOM異常浴井。
??? 5:方法區(qū)
???? 被各個線程共享,存儲被虛擬機(jī)加載的類的信息霉撵、常量磺浙、靜態(tài)變量等,為了與堆進(jìn)行區(qū)分徒坡,又有“非堆”的別名撕氧。
???? 由于在HotSpot虛擬機(jī)中把GC機(jī)制擴(kuò)展到了方法區(qū),使得垃圾收集器可以像Java堆那樣管理這部分內(nèi)存喇完,故方法區(qū)又叫“永久代”伦泥。這部分區(qū)域的垃圾回收為廢棄常量和無用的類。廢棄常量:常量池中沒有被任何對象引用的常量值锦溪。無用的類:無任何對象實(shí)例不脯、類加載器已被回收、Class對象沒有被引用的類文件刻诊。
???? 當(dāng)方法區(qū)內(nèi)存達(dá)到-XX:MaxPermSize上限時拋出OOM異常防楷。
GC算法
一:復(fù)制算法
??? 將可用內(nèi)存劃分為大小相等的兩塊。每次只使用其中一塊则涯,當(dāng)這塊內(nèi)存用完了就將仍然存活的對象復(fù)制到另一塊上复局,然后把已使用完的這一塊清理掉冲簿。這樣可以保證空閑區(qū)域總是連續(xù)的。復(fù)制算法一般用于新生代中的垃圾回收亿昏。
二:標(biāo)記—清除算法
??? 首先標(biāo)記出需要回收的對象民假,然后統(tǒng)一回收所有被標(biāo)記的對象。這種方法的不足之處在于:一是效率問題龙优,需要兩次遍歷;二是清除之后產(chǎn)生大量不連續(xù)的內(nèi)存碎片事秀,當(dāng)需要分配大內(nèi)存給較大對象時無法找到合適的連續(xù)空間而不得不提取觸發(fā)垃圾收集彤断。
三:標(biāo)記—整理算法
??? 對標(biāo)記—清除算法進(jìn)行改進(jìn):首先標(biāo)記出需要清理的對象,然后讓所有存活的對象向一端移動易迹,然后清理掉存活對象區(qū)域的邊界之外的內(nèi)存宰衙。這樣就使得回收產(chǎn)生的空閑區(qū)連續(xù)。
四:分代收集算法
??? 當(dāng)代的商業(yè)虛擬機(jī)都采用分代收集算法睹欲。對堆中的新生代采取復(fù)制算法供炼,老年代采取標(biāo)記—清除算法或者標(biāo)記—整理算法。
JVM分配策略
一:對象優(yōu)先分配在線程的本地分配緩沖區(qū)
?二:堆中優(yōu)先分配Eden
?三:大對象直接進(jìn)入老年代
?四:長期存活的對象“晉入”老年代
?五:空間分配擔(dān)保
?在MinorGC之前窘疮,會先檢查老年代最大可用空間是否可以容納新生代所有對象(防止新生代全部晉升時放不下)袋哼,如果可以容納,則MinorGC可以安全執(zhí)行闸衫。否則涛贯,檢查是否允許擔(dān)保失敗,是則檢查老年代最大可用空間是否大于歷次晉升到老年代的對象的平均大小蔚出,是則嘗試進(jìn)行MinorGC弟翘;小于或者M(jìn)inorGC失敗,則會發(fā)起一次FullGC清理老年代骄酗。
JVM類加載機(jī)制
虛擬機(jī)把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存稀余,并對數(shù)據(jù)進(jìn)行校驗(yàn)、轉(zhuǎn)換解析和初始化趋翻,最終成為被虛擬機(jī)直接使用的Java對象睛琳,這就是JVM的類加載機(jī)制。
類的生命周期
?類的生命周期包括7個部分:加載——驗(yàn)證——準(zhǔn)備——解析——初始化——使用——卸載
JVM調(diào)優(yōu)
JVM原理講解和調(diào)優(yōu) - Thinking的專欄 - CSDN博客
幾種情況:
舊生代空間不足
調(diào)優(yōu)時盡量讓對象在新生代GC時被回收踏烙、讓對象在新生代多存活一段時間和不要創(chuàng)建過大的對象及數(shù)組避免直接在舊生代創(chuàng)建對象
Pemanet Generation空間不足
增大Perm Gen空間掸掏,避免太多靜態(tài)對象
統(tǒng)計(jì)得到的GC后晉升到舊生代的平均大小大于舊生代剩余空間
控制好新生代和舊生代的比例
System.gc()被顯示調(diào)用
垃圾回收不要手動觸發(fā),盡量依靠JVM自身的機(jī)制
? ? 調(diào)優(yōu)手段主要是通過控制堆內(nèi)存的各個部分的比例和GC策略來實(shí)現(xiàn)宙帝,下面來看看各部分比例不良設(shè)置會導(dǎo)致什么后果
1)新生代設(shè)置過小
? ? 一是新生代GC次數(shù)非常頻繁丧凤,增大系統(tǒng)消耗;二是導(dǎo)致大對象直接進(jìn)入舊生代步脓,占據(jù)了舊生代剩余空間愿待,誘發(fā)Full GC
2)新生代設(shè)置過大
? ? 一是新生代設(shè)置過大會導(dǎo)致舊生代過泻坡荨(堆總量一定),從而誘發(fā)Full GC仍侥;二是新生代GC耗時大幅度增加
? ? 一般說來新生代占整個堆1/3比較合適
3)Survivor設(shè)置過小
? ? 導(dǎo)致對象從eden直接到達(dá)舊生代要出,降低了在新生代的存活時間
4)Survivor設(shè)置過大
? ? 導(dǎo)致eden過小,增加了GC頻率
? ? 另外农渊,通過-XX:MaxTenuringThreshold=n來控制新生代存活時間患蹂,盡量讓對象在新生代被回收
? ? 由內(nèi)存管理和垃圾回收可知新生代和舊生代都有多種GC策略和組合搭配,選擇這些策略對于我們這些開發(fā)人員是個難題砸紊,JVM提供兩種較為簡單的GC策略的設(shè)置方式
1)吞吐量優(yōu)先
? ? JVM以吞吐量為指標(biāo)传于,自行選擇相應(yīng)的GC策略及控制新生代與舊生代的大小比例,來達(dá)到吞吐量指標(biāo)醉顽。這個值可由-XX:GCTimeRatio=n來設(shè)置
2)暫停時間優(yōu)先
? ? JVM以暫停時間為指標(biāo)沼溜,自行選擇相應(yīng)的GC策略及控制新生代與舊生代的大小比例,盡量保證每次GC造成的應(yīng)用停止時間都在指定的數(shù)值范圍內(nèi)完成游添。這個值可由-XX:MaxGCPauseRatio=n來設(shè)置