JVM_淺析「堆與GC算法」

1、堆的組成部分

1-一、三大組成部分:

  • 新生代:新生代會頻繁觸發 MinorGC 進行垃圾回收算法

    • 伊甸園區(Eden):每次 new 出來的對象存放的位置。
    • 倖存者0區(ServivorFrom):每次gc垃圾回收的倖存者存放的位置。
    • 倖存者1區(ServivorTo):每次gc垃圾回收時,下一批倖存者存放的位置

    注意:默認內存比值爲 8:1:1,且每次 ServivorFromServivorTo,會交換位置的!性能

  • 老年代:當新生代的對象,被 gc 十五次以後,都還倖存,就存放到這裏。(若是new 的對象很大,也會直接放到這)優化

  • 永久代(方法區):存放着 jre 中自帶的一些類的信息,靜態變量,常量等數據,不過7以後,常量池都放到堆中去了!(這也就說明了,爲何它叫永久代,由於這些東西,咱們不須要管,因此8以後,把它用元空間取代了,由於它都不和咱們 new 出來的對象在一塊,因此乾脆把元空間歸於 本地內存!)對象

2、GC算法

2-一、何時進行垃圾回收?
  1. 新生代區域中的 Eden區滿了時,觸發 MinorGC (複製算法)
  2. 老年代區域中也滿了,觸發 MajorGC (標記清除算法)
2-二、何時進行垃圾回收?
如何肯定是否爲垃圾?
  • 引用計數法:若是一個對象實例,沒有引用地址指向它,那麼他的引用計數就是0,則斷定爲垃圾。內存

  • 可達性分析:爲了解決引用計數法的循環引用問題,Java 使用了可達性分析的方法。經過一系列的「GC roots」 對象做爲起點搜索。若是在「GC roots」和個對象之間沒有可達路徑,則稱該對象是不可達的。基礎

    要注意的是,不可達對象不等價於可回收對象,不可達對象變爲可回收對象至少要通過兩次標記 過程。兩次標記後仍然是可回收對象,則將面臨回收。變量

2-三、複製算法 (MinorGC)

過程:複製 => 清空 => 交換垃圾回收

  • 複製:首先把 EdenServivorFrom 的倖存者,複製到 ServivorTo 區域,而且讓倖存者年齡 +1,搜索

    ​ ,同時判斷倖存者年齡,若是年齡達到了 15 ,就轉移到老年區!循環

  • 清空:接着清空 EdenServivorFrom

  • 交換:交換 ServivorFromServivorTo ,以實現循環清理,直到年齡達到 老年區。

優勢:耗時較短,且不會有內存碎片。

缺點:須要額外的一塊空白的區域,進行幸存者轉移。

總結:空間換時間。適合存活率低的區域(新生代),存活率低,須要複製的倖存者就少,性能消耗的就少。

2-四、標記清除算法(MajorGC )

過程:掃描一次,進行標記,再掃描一次,進行清除。

標記:GCRoot算法,判斷是否爲垃圾,可清除。

優勢:不須要額外的空間,進行幸存者轉存。

缺點:耗時較長,並且會留下一塊塊的內存碎片!

總結:時間換空間。適合存活率高的區域,(老年代),倖存者較多,複製的話,太浪費性能了。

2-五、標記 整理/壓縮 清除算法

過程:在前者的基礎上,又多了一次掃描,而後將 倖存者 和 內存碎片 給整理到各自的整塊的領域。

優勢:不須要額外的空間,切沒有內存碎片殘餘。

缺點:耗時長!

總結:和前者相同,不過不宜頻繁使用!

2-六、體會

因爲 MajorGC 的內存碎片的緣故,若是能夠經過判斷 MajorGC 進行多少次後,內存碎片會比較多,而後進行一次內存碎片整理,應該算是一種優化!

相關文章
相關標籤/搜索