JVM:内存分配与回收策略?Full GC 的触发条件?StopTheWorld ?
內(nèi)存分配與回收策略
Minor GC 和 Full GC
-
Minor GC:發(fā)生在新生代上,因?yàn)樾律鷮?duì)象存活時(shí)間很短,因此 Minor GC 會(huì)頻繁執(zhí)行,執(zhí)行的速度一般也會(huì)比較快。
-
Full GC:發(fā)生在老年代上,老年代對(duì)象其存活時(shí)間長(zhǎng),因此 Full GC 很少執(zhí)行,執(zhí)行速度會(huì)比 Minor GC 慢很多。
內(nèi)存分配與回收策略
1. 對(duì)象優(yōu)先在 Eden 分配
大多數(shù)情況下,對(duì)象在新生代 Eden 區(qū)分配,當(dāng) Eden 區(qū)空間不夠時(shí),發(fā)起 Minor GC。
2. 大對(duì)象直接進(jìn)入老年代
大對(duì)象是指需要連續(xù)內(nèi)存空間的對(duì)象,最典型的大對(duì)象是那種很長(zhǎng)的字符串以及數(shù)組。
經(jīng)常出現(xiàn)大對(duì)象會(huì)提前觸發(fā)垃圾收集以獲取足夠的連續(xù)空間分配給大對(duì)象。
-XX:PretenureSizeThreshold,大于此值的對(duì)象直接在老年代分配,避免在 Eden 區(qū)和 Survivor 區(qū)之間的大量?jī)?nèi)存復(fù)制。
3. 長(zhǎng)期存活的對(duì)象進(jìn)入老年代
為對(duì)象定義年齡計(jì)數(shù)器,對(duì)象在 Eden 出生并經(jīng)過(guò) Minor GC 依然存活,將移動(dòng)到 Survivor 中,年齡就增加 1 歲,增加到一定年齡則移動(dòng)到老年代中。
-XX:MaxTenuringThreshold 用來(lái)定義年齡的閾值。
4. 動(dòng)態(tài)對(duì)象年齡判定
虛擬機(jī)并不是永遠(yuǎn)地要求對(duì)象的年齡必須達(dá)到 MaxTenuringThreshold 才能晉升老年代,如果在 Survivor 中相同年齡所有對(duì)象大小的總和大于 Survivor 空間的一半,則年齡大于或等于該年齡的對(duì)象可以直接進(jìn)入老年代,無(wú)需等到 MaxTenuringThreshold 中要求的年齡。
5. 空間分配擔(dān)保
在發(fā)生 Minor GC 之前,虛擬機(jī)先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對(duì)象總空間,如果條件成立的話,那么 Minor GC 可以確認(rèn)是安全的。
如果不成立的話虛擬機(jī)會(huì)查看 HandlePromotionFailure 設(shè)置值是否允許擔(dān)保失敗,如果允許那么就會(huì)繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對(duì)象的平均大小,如果大于,將嘗試著進(jìn)行一次 Minor GC;如果小于,或者 HandlePromotionFailure 設(shè)置不允許冒險(xiǎn),那么就要進(jìn)行一次 Full GC。
即使允許HandlePromotionFailure,也有可能會(huì)出現(xiàn)擔(dān)保失敗,因?yàn)椴豢赡芷骄稻桶俜种职偈穷A(yù)測(cè)正確的上限值!,所以這種情況下還是會(huì)進(jìn)行FULL GC!!!!
所以,通常情況下還是會(huì)打開(kāi)HandlePromotionFailure,這樣可以最大可能避免頻繁的FULL GC。
Full GC 的觸發(fā)條件
對(duì)于 Minor GC,其觸發(fā)條件非常簡(jiǎn)單,當(dāng) Eden 空間滿時(shí),就將觸發(fā)一次 Minor GC。而 Full GC 則相對(duì)復(fù)雜,有以下條件:
1. 調(diào)用 System.gc()
只是建議虛擬機(jī)執(zhí)行 Full GC,但是虛擬機(jī)不一定真正去執(zhí)行。不建議使用這種方式,而是讓虛擬機(jī)管理內(nèi)存。
2. 老年代空間不足
老年代空間不足的常見(jiàn)場(chǎng)景為前文所講的大對(duì)象直接進(jìn)入老年代、長(zhǎng)期存活的對(duì)象進(jìn)入老年代等。
為了避免以上原因引起的 Full GC,應(yīng)當(dāng)盡量不要?jiǎng)?chuàng)建過(guò)大的對(duì)象以及數(shù)組。除此之外,可以通過(guò) -Xmn 虛擬機(jī)參數(shù)調(diào)大新生代的大小,讓對(duì)象盡量在新生代被回收掉,不進(jìn)入老年代。還可以通過(guò) -XX:MaxTenuringThreshold 調(diào)大對(duì)象進(jìn)入老年代的年齡,讓對(duì)象在新生代多存活一段時(shí)間。
3. 空間分配擔(dān)保失敗
使用復(fù)制算法的 Minor GC 需要老年代的內(nèi)存空間作擔(dān)保,如果擔(dān)保失敗會(huì)執(zhí)行一次 Full GC。具體內(nèi)容請(qǐng)參考上面的第五小節(jié)。
4. JDK 1.7 及以前的永久代空間不足
在 JDK 1.7 及以前,HotSpot 虛擬機(jī)中的方法區(qū)是用永久代實(shí)現(xiàn)的,永久代中存放的為一些 Class 的信息、常量、靜態(tài)變量等數(shù)據(jù)。1.8之后去掉了永久代,將類信息放置在本地內(nèi)存空間(元空間)
當(dāng)系統(tǒng)中要加載的類、反射的類和調(diào)用的方法較多時(shí),永久代可能會(huì)被占滿,在未配置為采用 CMS GC 的情況下也會(huì)執(zhí)行 Full GC。如果經(jīng)過(guò) Full GC 仍然回收不了,那么虛擬機(jī)會(huì)拋出 java.lang.OutOfMemoryError。
為避免以上原因引起的 Full GC,可采用的方法為增大永久代空間或轉(zhuǎn)為使用 CMS GC。
5. Concurrent Mode Failure(CMS收集器產(chǎn)生的內(nèi)存碎片后,老年代無(wú)法放入連續(xù)大對(duì)象)
執(zhí)行 CMS GC 的過(guò)程中同時(shí)有對(duì)象要放入老年代,而此時(shí)老年代空間不足(可能是 GC 過(guò)程中浮動(dòng)垃圾過(guò)多導(dǎo)致暫時(shí)性的空間不足),便會(huì)報(bào) Concurrent Mode Failure 錯(cuò)誤,并觸發(fā) Full GC。
StopTheWorld
GC的時(shí)候?yàn)槭裁匆猄topTheWorld(全局停頓)???
在GC的時(shí)候,進(jìn)行標(biāo)記過(guò)程時(shí),可達(dá)性分析必須要在一個(gè)可以保證一致性的快照中執(zhí)行!也就是說(shuō),不可以出現(xiàn)在分析過(guò)程中對(duì)象的引用關(guān)系還在不斷變化的情況,該點(diǎn)不滿足的話,分析結(jié)果的準(zhǔn)確性就不能夠得到保證!!!!(這一點(diǎn)可以類比于你媽打掃你的房間的問(wèn)題)
總結(jié)
以上是生活随笔為你收集整理的JVM:内存分配与回收策略?Full GC 的触发条件?StopTheWorld ?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 获取application.yml中的属
- 下一篇: jvm:类加载器与双亲委派模型