圖解 Java 垃圾回收機制,寫得非常好!

JAVA架構發表於2019-06-12

原文:

譯文:

翻譯:Rhys_Lee, AzureSora, 溪邊九節, 小小菜鳥雞

Java架構/分散式:705127209(大牛交流群)沒有開發經驗勿加!

什麼是自動垃圾回收?

自動垃圾回收是一種在堆記憶體中找出哪些物件在被使用,還有哪些物件沒被使用,並且將後者刪掉的機制。

所謂使用中的物件(已引用物件),指的是程式中有指標指向的物件;而未使用中的物件(未引用物件),則沒有被任何指標給指向,因此佔用的記憶體也可以被回收掉。

在用 C 之類的程式語言時,程式設計師需要自己手動分配和釋放記憶體。而 Java 不一樣,它有垃圾回收器,釋放記憶體由回收器負責。本文接下來將介紹垃圾回收機制的基本過程。

第一步:標記

垃圾回收的第一步是標記。垃圾回收器此時會找出哪些記憶體在使用中,還有哪些不是。

圖解 Java 垃圾回收機制,寫得非常好!

上圖中,藍色表示已引用物件,橙色表示未引用物件。垃圾回收器要檢查完所有的物件,才能知道哪些有被引用,哪些沒。如果系統裡所有的物件都要檢查,那這一步可能會相當耗時間。

第二步:清除

這一步會刪掉標記出的未引用物件。

圖解 Java 垃圾回收機制,寫得非常好!

記憶體分配器會保留指向可用記憶體的引用,以供分配新物件。

壓縮

為了提升效能,刪除了未引用物件後,還可以將剩下的已引用物件放在一起(壓縮),這樣就能更簡單快捷地分配新物件了。

圖解 Java 垃圾回收機制,寫得非常好!

為什麼需要分代垃圾收集?

之前說過,逐一標記和壓縮 Java 虛擬機器裡的所有物件非常低效:分配的物件越多,垃圾回收需時就越久。不過,根據統計,大部分的物件,其實用沒多久就不用了。

來看個例子吧。(下圖中,豎軸代表已分配的位元組,而橫軸代表程式執行時間)

圖解 Java 垃圾回收機制,寫得非常好!

上圖可見,存活(沒被釋放)的物件隨執行時間越來越少。而圖中左側的那些峰值,也表明了大部分物件其實都挺短命的。

JVM 分代

根據之前的規律,就可以用來提升 JVM 的效率了。方法是,把堆分成幾個部分(就是所謂的分代),分別是新生代、老年代,以及永生代。

圖解 Java 垃圾回收機制,寫得非常好!

新物件會被分配在新生代記憶體。一旦新生代記憶體滿了,就會開始對死掉的物件,進行所謂的 小型垃圾回收 過程。一片新生代記憶體裡,死掉的越多,回收過程就越快;至於那些還活著的物件,此時就會老化,並最終老到進入老年代記憶體。

Stop the World 事件—— 小型垃圾回收屬於一種叫 "Stop the World" 的事件。在這種事件發生時,所有的程式執行緒都要暫停,直到事件完成(比如這裡就是完成了所有回收工作)為止。

老年代用來儲存長時間存活的物件。通常,設定一個閾值,當達到該年齡時,年輕代物件會被移動到老年代。最終老年代也會被回收。這個事件成為 Major GC。

Major GC 也會觸發STW(Stop the World)。通常,Major GC會慢很多,因為它涉及到所有存活物件。所以,對於響應性的應用程式,應該儘量避免Major GC。還要注意,Major GC的STW的時長受年老代垃圾回收器型別的影響。

永久代包含JVM用於描述應用程式中類和方法的後設資料。永久代是由JVM在執行時根據應用程式使用的類來填充的。此外,Java SE類庫和方法也儲存在這裡。

如果JVM發現某些類不再需要,並且其他類可能需要空間,則這些類可能會被回收。

世代垃圾收集過程

現在你已經理解了為什麼堆被分成不同的代,現在是時候看看這些空間是如何相互作用的。 後面的圖片將介紹JVM中的物件分配和老化過程。

首先,將任何新物件分配給 eden 空間。 兩個 survivor 空間都是空的。

圖解 Java 垃圾回收機制,寫得非常好!

當 eden 空間填滿時,會觸發輕微的垃圾收集。

圖解 Java 垃圾回收機制,寫得非常好!

引用的物件被移動到第一個 survivor 空間。 清除 eden 空間時,將刪除未引用的物件。

圖解 Java 垃圾回收機制,寫得非常好!

在下一次Minor GC中,Eden區也會做同樣的操作。刪除未被引用的物件,並將被引用的物件移動到Survivor區。然而,這裡,他們被移動到了第二個Survivor區(S1)。

此外,第一個Survivor區(S0)中,在上一次Minor GC倖存的物件,會增加年齡,並被移動到S1中。待所有幸存物件都被移動到S1後,S0和Eden區都會被清空。注意,Survivor區中有了不同年齡的物件。

圖解 Java 垃圾回收機制,寫得非常好!

在下一次Minor GC中,會重複同樣的操作。不過,這一次Survivor區會交換。被引用的物件移動到S0,。倖存的物件增加年齡。Eden區和S1被清空。

圖解 Java 垃圾回收機制,寫得非常好!

 此幻燈片演示了 promotion。 在較小的GC之後,當老化的物體達到一定的年齡閾值(在該示例中為8)時,它們從年輕一代晉升到老一代。

圖解 Java 垃圾回收機制,寫得非常好!

隨著較小的GC持續發生,物體將繼續被推廣到老一代空間。

圖解 Java 垃圾回收機制,寫得非常好!

所以這幾乎涵蓋了年輕一代的整個過程。 最終,將主要對老一代進行GC,清理並最終壓縮該空間。

圖解 Java 垃圾回收機制,寫得非常好!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69912582/viewspace-2647461/,如需轉載,請註明出處,否則將追究法律責任。

相關文章