3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

對於不再有用的對象,Java有垃圾自動回收機制(Garbage Collection,GC)。哪些東西會被垃圾收集器 (Garbage Collector)認定為不再有用的對象?簡單地說,

任何無法被JVM中正在執行的線程通過引用變量名追尋到的對象,就是GC認定的垃圾

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

具體來講,在Java中採取了可達性分析法。原理是通過一系列的“GC Roots”對象作為起點進行搜索,如果在“GC Roots”和一個對象之間沒有任何可達路徑,則稱該對象是不可達的,但是要注意,被判定為不可達的對象不一定就會成為可回收對象。被判定為不可達的對象要成為可回收對象必須至少經歷兩次標記過程,如果在這兩次標記過程中仍然沒有逃脫成為可回收對象的可能性,則基本上就真的成為可回收對象了。

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

本文只是簡單示例對象成為垃圾的情形,通常情況,在啟動JVM之後,JVM中就會有一些執行線程,最基本的,就是程序執行入口的主執行線程(main thread),基本上,main 主線程是你要關心對象是否成為垃圾的起點。

假設有一個類:

public class Some {

Some next;

}

如果在main 方法中有這樣一段代碼:

Some some1 = new Some();

Some some2 = new Some();

Some some1 = some2;

執行到第二行時,主線程通過變量名可達對象為:

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

執行到第三行時,是將some2對象賦值給some1,這時some1指向some2:

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

這個時候,原先被some1引用的對象不再被任何變量引用,通過主線程也不再可以找到該對象,這個對象就是內存中的垃圾了,GC會自動找出這些垃圾並予以回收。

如果是建立的新的線程,例如:

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

在someMethod()執行過後,只要建立的執行線程還沒有離開run()方法,也就是執行線程還沒進入dead狀態,則該執行線程所引用的對象就一直還可以利用,也就不會被垃圾回收。

如果有這樣一段代碼:

Some some = new Some();

some.next = new Some();

some = null;

在執行到第二行時,情況為這樣:

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

當執行到第三行時,變為這樣:

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

這個時候,some原先所引用的對象,會被回收,而next所引用的對象也因無法被任何線程可達,也會被回收。所以同樣地道理,下面的代碼中,對象數組所引用到的對象全部都會被回收:

Some[] somes = {new Some(), new Some(), new Some};

somes = null;

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

還有一種情況,形成孤島的對象,例如:

Some some = new Some();

some.next = new Some();

some.next.next = new Some();

some.next.next.next = some;

some = null;

當執行到第四行代碼時,

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

當執行到第五行代碼時,

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?

這個時候右邊的對象形成了一個孤島,將全部被GC給回收掉。

3分鐘瞭解:Java垃圾收集器(GC)如何確定哪些是“垃圾”?


分享到:


相關文章: