空間分配擔保

2022-07-02 11:48:08 字數 3088 閱讀 8913

新生代採用的複製演算法,留空乙個 survivor 作為空間備份,當大量物件在 minor gc後仍然存活,survivor 無法放下,則會直接進入老年代, 需要老年代的空間保證能容納得下這些物件。

空間擔保比較的是 老年代最大的連續空閒空間 和 年輕代所有物件的記憶體大小 或 歷次晉公升到老年代的平均物件大小做比較

分配擔保機制中,無論是新生代所有物件總和還是歷次晉公升到老年代的平均大小的經驗值,在進行比較時候都會和老年代最大連續空間進行比較。 難道不連續只要湊起來夠就不行了?畢竟老年代還是 標記-清理-(壓縮) 演算法。

參考 確實不行,因為:

如果 最大連續空閒空間大於歷次晉公升的平均大小 ,但是這次存活的物件突增,老年代放不下 只好在失敗後進行一次 full gc

並不能減少 full gc ,該來的終歸會來的

public class promotiontest 

}

eden區8m,建立了3個2m物件後 占用的記憶體超過6m,因為每個物件本身 還有物件頭等需要占用一點記憶體;所以當要建立第4個物件的時候 eden就放不下 需要進行 minor gc了

執行日誌

-----create a1------

-----create a2------

-----create a3------

[gc (allocation failure) [defnew: 6325k->543k(9216k), 0.0035420 secs] 6325k->4639k(15360k), 0.0035620 secs] [times: user=0.00 sys=0.00, real=0.00 secs]

第一次 分配失敗

當要建立 a4的時候,進行 minor gc, **掉 a1,由於survivor放不下a2和a3,直接進入老年代; 此時:年輕代: 空, 老年代: a2, a3

9216k = eden + suvivor * 1

繼續建立 a4、a5、a6,都在年輕代中

-----clear a1 ------

-----create a4------

-----create a5------

-----create a6------

[gc (allocation failure) [defnew: 6924k->6924k(9216k), 0.0000118 secs][tenured: 4096k->4097k(6144k), 0.0023158 secs] 11020k->8654k(15360k), [metaspace: 3026k->3026k(1056768k)], 0.0023555 secs] [times: user=0.01 sys=0.00, real=0.01 secs]

**第二次 分配失敗

**建立 a7 的時候,eden放不下了,需要先進行gc ,但是由於「分配擔保」機制

老年代目前 5m - 2m*2 放不下年輕代所有物件,也放不下之前晉公升的 a2+a3的空間大小,擔保失敗了; jdk1.6 update24之後 handlepromotionfailure失效了,所以這邊故意把老年代設定成比較小的 5m

-----clear a4 ------

-----clear a5 ------

-----clear a6 ------

-----create a7------

[full gc(allocation failure) [tenured: 4097k->4549k(6144k), 0.0016231 secs] 10995k->4549k(15360k), [metaspace: 3034k->3034k(1056768k)], 0.0016412 secs] [times: user=0.00 sys=0.00, real=0.00 secs]

分配擔保失敗,進行 full gc

老年代裡邊的 a2 和 a3 還存活 記憶體不變

年輕代的 a4、a5、a6 無引用了,**掉;

heap

def new generation total 9216k, used 2138k[0x00000007bf000000, 0x00000007bfa00000, 0x00000007bfa00000)

eden space 8192k, 26% used [0x00000007bf000000, 0x00000007bf216b60, 0x00000007bf800000)

from space 1024k, 0% used [0x00000007bf900000, 0x00000007bf900000, 0x00000007bfa00000)

to space 1024k, 0% used [0x00000007bf800000, 0x00000007bf800000, 0x00000007bf900000)

tenured generation total 6144k, used 4549k[0x00000007bfa00000, 0x00000007c0000000, 0x00000007c0000000)

the space 6144k, 74% used [0x00000007bfa00000, 0x00000007bfe717e0, 0x00000007bfe71800, 0x00000007c0000000)

metaspace used 3050k, capacity 4496k, committed 4864k, reserved 1056768k

class space used 333k, capacity 388k, committed 512k, reserved 1048576k

從分配擔保的邏輯中,可以看出 分配擔保最關鍵作用是,在進行minor gc前是否需要根據歷屆晉公升到老年代的平均值來發起一次full gc. 換句話來說,去掉分配擔保(也就是相當於引數handlepromotionfailure=false)就意味著full gc發生的機率更大。

分配擔保機制可以不要,但會導致full gc更容易發生,進而導致所謂的stop the world,虛擬機器短暫停止,吞吐量,效能下降。 有了分配擔保機制,就可以借鑑經驗值來減少full gc這種耗時降低效能行為。

JVM 空間分配擔保

在發生minor gc之前,虛擬機會檢測 老年代最大可用的連續空間 新生代all物件總空間?1 滿足,minor gc是安全的,可以進行minor gc。2 不滿足,虛擬機器檢視handlepromotionfailure引數 1 為true,允許擔保失敗,會繼續檢測老年代最大可用的連續空間 歷次晉...

jvm分配擔保機制

在發生minor gc之前,虛擬機會先檢查老年代最大可用的連續空間是否大於新生代所有物件總空間。如果這個條件成立,那麼minor gc可以確保是安全的。如果不成立,則虛擬機會檢視handlerpromotionfailure設定是否允許擔保失敗。如果允許,那麼會繼續檢查老年代最大可用的連續空間是否大...

一句話解釋JVM中空間分配擔保的問題

先解釋ygc 當物件生成在eden區失敗時,出發一次ygc,先掃瞄eden區中的存活物件,進入s0區,s0放不下的進入old區,再掃瞄s1區,若存活次數超過閥值則進入old區,其它進入s0區,然後s0和s1交換一次。那麼當發生ygc時,jvm會首先檢查老年代最大的可用連續空間是否大於新生代所有物件的...