歡迎光臨
每天分享高質量文章

Java 垃圾回收機制

來自:開源中國

鏈接:https://www.oschina.net/translate/java-gc

原文:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html#t3


什麼是自動垃圾回收?


自動垃圾回收是一種在堆記憶體中找出哪些物件在被使用,還有哪些物件沒被使用,並且將後者刪掉的機制。所謂使用中的物件(已取用物件),指的是程式中有指標指向的物件;而未使用中的物件(未取用物件),則沒有被任何指標給指向,因此占用的記憶體也可以被回收掉。


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


第一步:標記


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


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


第二步:清除


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



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


壓縮


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


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


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

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



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


JVM 分代


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



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


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 空間都是空的。


(ps:物件優先在 eden 區中分配,目前主流的垃圾收集器會採用分代回收演算法,因此需要將堆記憶體分為新生代和老年代。


在新生代中為了防止記憶體碎片問題,因此垃圾收集器一般選用 複製 演算法,所以堆記憶體的新生代又被分為 eden 區 + survivor 1區 + survivor2 區。)



當 eden 空間填滿時,則會觸發一次小的垃圾收集。



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



在下一次Minor GC中,Eden區也會做同樣的操作。刪除未被取用的物件,並將被取用的物件移動到Survivor區。然而,這裡,他們被移動到了第二個Survivor區(S1)。此外,第一個Survivor區(S0)中,在上一次Minor GC幸存的物件,會增加年齡,並被移動到S1中。待所有幸存物件都被移動到S1後,S0和Eden區都會被清空。註意,Survivor區中有了不同年齡的物件。



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



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



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



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


●編號783,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

演算法與資料結構

更多推薦18個技術類公眾微信

涵蓋:程式人生、演算法與資料結構、黑客技術與網絡安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

赞(0)

分享創造快樂