溫馨提示×

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

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

java之分配和管理JVM內(nèi)存

發(fā)布時(shí)間:2020-05-08 10:47:18 來源:億速云 閱讀:207 作者:Leah 欄目:編程語言

這篇文章主要為大家詳細(xì)介紹了java分配和管理JVM內(nèi)存的方法,文中示例介紹的非常詳細(xì),圖文詳解容易學(xué)習(xí),非常適合初學(xué)者入門。

一.垃圾搜集算法

  • JVM中的內(nèi)存分配機(jī)制

    垃圾回收算法有標(biāo)記-清除算法,標(biāo)記-整理算法和復(fù)制算法,JVM使用分代收集算法來回收J(rèn)VM分配的內(nèi)存空間,分代收集算法分為新生代和老年代,主要收集JVM內(nèi)存模型中的堆內(nèi)存,其中新生代使用復(fù)制算法,老年代使用標(biāo)記-整理算法,下面探索下垃圾回收算法的具體思想。

  • 標(biāo)記-清除算法:
    標(biāo)記清除算法分為標(biāo)記和清除兩個(gè)階段,首先標(biāo)記出需要回收的內(nèi)存空間,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象。它的主要確定有兩個(gè):1.它的標(biāo)記和清除的效率都不高。2.它清除對(duì)象空間后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,使得再分配大對(duì)象(需要使用大量連續(xù)內(nèi)存的對(duì)象)時(shí)因內(nèi)存不足問題而提前觸發(fā)垃圾回收。它的回收過程如下圖所示。

java之分配和管理JVM內(nèi)存

  • 復(fù)制算法
    復(fù)制算法將內(nèi)存容量劃分為相等的兩塊,每次使用其中的一塊內(nèi)存,當(dāng)這塊內(nèi)存使用完了,就將這塊內(nèi)存中存活的對(duì)象復(fù)制到另一塊內(nèi)存中,然后清空這塊內(nèi)存空間,下次的對(duì)象分配到另一塊內(nèi)存空間中,也就是存儲(chǔ)的有對(duì)象的那塊,兩塊內(nèi)存空間交替使用。在JVM堆內(nèi)存中的新生代分為Eden空間,from survivor空間和to survivor空間。默認(rèn)Eden和survivor空間比例是8:1,其中Eden占80%,from 和 to 各占10%,所有新生代的內(nèi)存能夠利用的空間為90%。在新生代中,每次垃圾回收都會(huì)有大量的對(duì)象被回收掉,所以只需要復(fù)制存活的少數(shù)對(duì)象即可。下面是復(fù)制算法的操作過程:

java之分配和管理JVM內(nèi)存

  • 標(biāo)記-整理算法:
    復(fù)制算法在對(duì)象存活率較高的情況下并不好用,因?yàn)樗?jīng)過復(fù)制大量的存活對(duì)象。更關(guān)鍵的是,復(fù)制算法會(huì)有一些空間浪費(fèi)掉。因?yàn)槔夏甏4娴氖且恍┐婊钪芷诒容^長(zhǎng)的對(duì)象,所以不適合使用復(fù)制算法。根據(jù)老年代的特點(diǎn),產(chǎn)生了標(biāo)記-整理算法。標(biāo)記-整理算法先標(biāo)記存活的對(duì)象,然后讓他們向一端移動(dòng),之后再釋放掉端邊界以外的對(duì)象內(nèi)存。標(biāo)記-整理算法執(zhí)行過程如下:

java之分配和管理JVM內(nèi)存

二.內(nèi)存分配和回收策略
java技術(shù)體系中所提倡的自動(dòng)內(nèi)存管理最終可以歸結(jié)為自動(dòng)化的給對(duì)象分配內(nèi)存以及回收分配給對(duì)象的內(nèi)存。關(guān)于回收內(nèi)存可以參考上面的垃圾收集算法,JVM采用分代垃圾回收算法來回收對(duì)象內(nèi)存,分為新生代和老年代,新生代使用復(fù)制算法,老年代使用標(biāo)記-整理算法。下面來看下JVM的內(nèi)存分配策略:

  • 對(duì)象優(yōu)先在Eden區(qū)分配
    大多數(shù)情況下,對(duì)象在新生代Eden區(qū)分配。當(dāng)Eden區(qū)沒有足夠的內(nèi)存空間進(jìn)行分配時(shí),虛擬機(jī)將發(fā)起一次Minor GC(新生代GC)來回收新生代中已經(jīng)死亡的對(duì)象,存活的對(duì)象存儲(chǔ)到survivor區(qū)中,如果survivor區(qū)沒有足夠的空間存儲(chǔ),將通過空間分配擔(dān)保直接存入老年代中。之后把對(duì)象存入Eden區(qū)。

  • 大對(duì)象直接進(jìn)入老年代
    大對(duì)象指的是需要大量連續(xù)內(nèi)存空間的對(duì)象,最典型的大對(duì)象為很長(zhǎng)的字符串和很長(zhǎng)的數(shù)組。大對(duì)象對(duì)虛擬機(jī)的內(nèi)存分配來說是一個(gè)壞消息,經(jīng)常出現(xiàn)大對(duì)象容易導(dǎo)致內(nèi)存還有不少空間時(shí)就提前觸發(fā)垃圾回收及產(chǎn)生連續(xù)的空間來存放大對(duì)象。不大對(duì)象更糟糕的情況是遇到一群“短命”的大對(duì)象,寫程序時(shí)應(yīng)避免。

  • 長(zhǎng)期存活的對(duì)象進(jìn)入老年代
    既然虛擬機(jī)采用了分代收集的思想來管理內(nèi)存,那虛擬機(jī)就要知道哪些對(duì)象應(yīng)該放在新生代,哪些對(duì)象應(yīng)該放在老年代。虛擬機(jī)給每個(gè)對(duì)象了一個(gè)年齡計(jì)數(shù)器。如果這個(gè)對(duì)象在Eden區(qū)中經(jīng)歷了一此Minor GC,并存儲(chǔ)到了survivor區(qū)中,那這個(gè)對(duì)象的年齡為1,每熬過一次MinorGC,對(duì)象的年齡加1,當(dāng)他的年齡增加到一定程度(默認(rèn)是15歲),就會(huì)晉升到老年代中。

  • 動(dòng)態(tài)對(duì)象年齡判定
    為了能更好的適應(yīng)不同程序的內(nèi)存狀況,虛擬機(jī)并不總是只有在對(duì)象的年齡達(dá)到一定程度時(shí)才讓對(duì)象進(jìn)入老年代,如果在survivor空間的相同年齡的對(duì)象內(nèi)存總和大于survivor空間內(nèi)存的一半時(shí),大于等于這個(gè)年齡的對(duì)象將進(jìn)入老年代中。

  • 空間分配擔(dān)保
    老年代會(huì)為新生代的內(nèi)存分配做擔(dān)保,也就是說在進(jìn)行Minor GC之前,虛擬機(jī)會(huì)先檢查老年代的最大連續(xù)可用內(nèi)存空間是否大于等于新生代所有對(duì)象總空間,如果大于等于,就說明這次Minor GC是安全的,因?yàn)镸inor GC后可能會(huì)出現(xiàn)把新生代對(duì)象存儲(chǔ)到老年代中的情況(當(dāng)Minor GC后surviror空間內(nèi)存不夠用時(shí)),如果這個(gè)條件不成立,那虛擬機(jī)會(huì)查看HandlePromotionFailure設(shè)置是否允許擔(dān)保失敗,允許的話,虛擬機(jī)會(huì)看老年代最大連續(xù)可用空間的大小是否大于歷次晉升到老年代的對(duì)象平均大小,如果大于,虛擬機(jī)會(huì)嘗試進(jìn)行一次Minor GC。如果不允許擔(dān)保失敗,就會(huì)進(jìn)行Full GC(老年代GC)來回收老年代死亡對(duì)象的空間好讓老年代騰出更大的空間。

看完上訴內(nèi)容,你們掌握java分配和管理JVM內(nèi)存的方法了嗎?如果想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(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