垃圾收集器與內存分配策略——內存分配策略與回收策略

內存分配策略與回收策略

參考:《深入理解Java虛擬機》-jvm高級特性與最佳實現(周志明著)

前言

Java技術體系所倡導的內存管理最終可以貴大爲自動化解決兩個問題:給對象分配內存以及回收分配給對象的內存。

如下的內容是基於Client模式下默認的垃圾收集器組合

一、內存分配的普遍規則

1、對象優先在Eden空間分配,大多情況下,對象在新生代的Eden空間進行分配,當Eden空間沒有足夠的內存時,將觸發一次Minor GC,可以通過設置-XX:+PrintGCDetails 這個收集器日誌參數,高速虛擬機在發生垃圾回收的時候打印GC日誌。

注意:

Minor GC 和 Full GC 有什麼不一樣嗎?

新生代GC(Minor GC):是指新生代的垃圾收集動作,因爲Java對象大多朝生夕滅,所以Minor GC發生的非常頻繁。一般回收速度也比較快。

老年代GC(Major GC / Full GC):Major GC清理Tenured區,用於回收老年代,出現Major GC通常會出現至少一次Minor GC。

Full GC是針對整個新生代、老生代、元空間(metaspace,java8以上版本取代perm gen)的全局範圍的GC。Full GC不等於Major GC,也不等於Minor GC+Major GC,發生Full GC需要看使用了什麼垃圾收集器組合,才能解釋是什麼樣的垃圾回收。

2、大對象直接進入老年代,最典型的大對象就算是指那種很長的字符串以及數組。虛擬機提供了-XX:PretenureSizeThreshold 參數,令大於這個設置值的對象直接在老年代分配。這樣做的目的是避免在Eden空間以及兩個Survivor區之間發生大量的 內存複製。

需要注意的是,-XX:PretenureSizeThreshold 這個參數對Parallel Scavenge 收集器不起作用,如果遇到必須使用該設置的場合,可以考慮使用ParNew 加 CMS 收集器組合

3、長期存活的對象將進入老年代

虛擬機給每個對象都定義了一個年齡計數器,如果對象在Eden出生,並經過第一次Minor GC 後存活,並且被Survivor容納的話,將被移動到Survivor空間中,並且對象年齡設置爲1,對象在Survivor區中每熬過一次Minor GC,年齡就增加1歲,當它的年齡增加超過默認(15歲)的時候,會被晉升到老年代中,對象晉升老年代的年齡閾值,可以通過設置參數 -XX:MaxTenuringThreshold設置

4、動態對象年齡判斷

爲了更好地適應不同程序的內存情況,虛擬機並不是永遠地要求對象的年齡必須達到MaxTenuringThreshold 才能晉升老年代。如果再Survivor空間中相同年齡的所有對象大小的總和超過了Survivor空間的一半,年齡大於等於該年齡的對象就可以直接進入到老年代。

5、空間分配擔保

在發生Minor GC之前,虛擬機會先檢查老年代最大可用的連續空間是否大於新生代所有對象的總和。如果這個條件成立,那麼Minor GC 可以確保實施安全的。如果不成立,則虛擬機會查看HandlerPromotionFailure設置是否允許擔保失敗。如果允許,那麼就會繼續檢查老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,如果大於,將嘗試一次Minor GC,儘管這次Minor GC 是有風險的。如果小於或者HandlerPromotionFailure設置的值不允許冒險,那這時也要改爲進行一次Full GC

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章