“嗨!我決定再給你上一堂關於垃圾回收的小課。”

正如您已經知道的那樣,Java 機器本身會監視一個對象何時變得不需要,並將其刪除。

“是的,之前你和Rishi跟我說過,具體的我不記得了。”

“好吧。那我們再說一遍。”

垃圾收集 - 1

“一旦創建了一個對象,JVM 就會為它分配內存。使用引用變量來監視對對象的興趣。 可以在垃圾收集期間刪除一個對象,即如果沒有引用該對象的變量,則釋放內存的過程對象。

“告訴我一些關於垃圾收集器的信息——它是什麼以及它是如何工作的。”

“好吧。過去垃圾收集發生在主線程上。每 5 分鐘一次,或更頻繁。如果沒有足夠的可用內存,Java 機器將掛起所有線程並刪除未使用的對象。”

“但這種方法現在已經被放棄了。下一代垃圾收集器在幕後和一個單獨的線程上工作。這被稱為並發垃圾收集。”

“我明白了。刪除或不刪除對象的決定究竟是如何做出的?”

“僅僅計算對一個對象的引用次數並不是很有效——可能有一些對象相互引用,但沒有被其他對象引用。”

”所以Java採取了不同的方法。Java 將對象分為可達和不可達。 如果一個對像被另一個可達(活)對象引用,則該對像是可達(活著)。可達性由線程決定。運行線程總是被認為是可達(活著) ,即使沒有人提及它們。”

“好的。我想我明白了。”

“實際的垃圾收集是如何發生的——刪除不需要的對象?”

“很簡單。在 Java 中,內存按照慣例被分成兩部分,當垃圾回收的時候,所有活著的(可達的)對像被複製到另一部分內存中,舊的內存全部被釋放。”

“這是一種有趣的方法。無需計算引用:複製所有可達的對象,其他一切都是垃圾。”

“它比那要復雜一點。Java 程序員發現對象通常分為兩類:長壽命的(在程序運行的整個過程中都存在)和短壽命的(在方法中和執行 «local » 操作)。

“將長壽命的物體與短壽命的物體分開會更有效率。為此,有必要想出一種方法來確定物體的壽命。”

“所以,他們把所有的內存都分成了«generations»。有第一代對象,第二代對像等。每次清除內存時,generation counter加1。如果某些對象存在多代,那麼它們被記錄為長壽。”

“今天,垃圾收集器是 Java 中一個非常複雜和高效的部分。它的許多部分都以啟發式的方式工作——基於進行猜測的算法。結果,它經常“不聽”用戶的意見。”

“意義?”

“Java 有一個垃圾收集器 ( GC ) 對象,可以使用System.gc () 方法調用。”

“您還可以使用System.runFinalization()強制調用要刪除的對象的終結方法。但事實是,根據 Java 文檔,這既不保證垃圾收集將開始,也不保證終結( ) 方法將被調用。 垃圾收集器決定何時調用它以及調用什麼。

“哇!很高興知道。”

“但還有更多。如您所知,在 Java 中,一些對象引用其他對象。這種引用網絡用於確定是否應刪除一個對象。”

“而且,你看。Java 有特殊的引用,可以讓你影響這個過程。它們有特殊的包裝類。它們在這裡:”

SoftReference 是軟引用。”

WeakReference 是弱引用。”

PhantomReference是一個虛引用。”

“呃……這讓我想起了內部類、嵌套類、嵌套匿名類、局部類,名字不一樣,但完全搞不清楚是乾什麼用的。”

“說,阿米戈,你已經成為一名程序員。現在你因為類名而生氣,說 «它們沒有提供足夠的信息,而且不可能用一個名字(!)來確定這個類做什麼,如何,以及為什麼»。

“哇。我都沒注意到。但它是如此明顯。”

“好的。廢話不多說了。讓我告訴你有關 SoftReferences 的事。”

“這些引用是專門為緩存而設計的,儘管它們也可以用於其他目的——完全由程序員自行決定。”

“這是此類參考的示例:”

例子
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

“如果對一個對象的唯一引用是軟的,那麼它會繼續存在並被稱為‘軟可達’。”

“但是! 如果程序沒有足夠的內存,垃圾收集器可以刪除僅由軟引用引用的對象。 如果程序突然沒有足夠的內存,在拋出 OutOfMemoryException 之前垃圾收集器將刪除所有對象被軟引用引用並將再次嘗試為程序分配內存。”

“假設客戶端程序經常向服務器程序請求各種數據。服務器程序可以使用軟引用來緩存其中的一些數據。如果通過軟引用免於死亡的對象佔用了大部分內存,那麼垃圾收集器會簡單地刪除它們一切。它很漂亮!

“嗯。我自己也喜歡。”

“嗯,一個小補充:SoftReference類有兩個方法。get() 方法返回SoftReference引用的對象。如果對像被垃圾收集器刪除,get () 方法將突然開始返回 null。”

“用戶也可以通過調用 clear() 方法顯式清除SoftReference 。在這種情況下, SoftReference對象內部的弱鏈接將被破壞。”

“目前為止就這樣了。”

“謝謝你的有趣故事,艾莉。真的很有趣。”