溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java內(nèi)存分配與回收策略

發(fā)布時(shí)間:2021-09-13 14:57:27 來(lái)源:億速云 閱讀:77 作者:chen 欄目:編程語(yǔ)言

本篇內(nèi)容介紹了“Java內(nèi)存分配與回收策略”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

內(nèi)存分配與回收策略

Minor GC 和 Full GC

  • Minor GC:發(fā)生在新生代上,因?yàn)樾律鷮?duì)象存活時(shí)間很短,因此 Minor GC 會(huì)頻繁執(zhí)行, 執(zhí)行的速度一般也會(huì)比較快。

  • Full GC:又稱Major GC,發(fā)生在老年代上,老年代對(duì)象其存活時(shí)間長(zhǎng), 因此 Full GC 很少執(zhí)行,執(zhí)行速度會(huì)比 Minor GC 慢很多。

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。

Full GC 的觸發(fā)條件

對(duì)于 Minor GC,其觸發(fā)條件非常簡(jiǎn)單,當(dāng) Eden 空間滿時(shí),就將觸發(fā)一次 Minor GC。 而 Full GC 則相對(duì)復(fù)雜,有以下條件:

  • 相應(yīng)腦圖

1. 調(diào)用 System.gc()

只是建議虛擬機(jī)執(zhí)行 Full GC,但是虛擬機(jī)不一定真正去執(zhí)行。不建議使用這種方式,而是讓虛擬機(jī)管理內(nèi)存。

2. 老年代空間不足

老年代空間不足的常見場(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ù)。

當(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

執(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。

“Java內(nèi)存分配與回收策略”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI