CodeGym /Java Blog /Toto sisi /關於垃圾收集器的更多信息
John Squirrels
等級 41
San Francisco

關於垃圾收集器的更多信息

在 Toto sisi 群組發布
你好!在上節課中,我們首先熟悉了Java內置的垃圾收集器,並大致了解了它的工作原理。它在您的程序運行時在後台工作,收集稍後將被刪除的不必要的對象。因此,它釋放了可用於在將來創建新對象的內存。
關於垃圾收集器的更多信息 - 1
在本課中,我們將更詳細地討論它是如何工作的。例如,一個對像如何以及何時變得不必要?垃圾收集器如何發現?這些是我們將在今天的課程中回答的問題 :) 本課程將更像是一個概述:您不需要死記硬背這些材料。目的主要是擴展您對內存和垃圾收集器工作原理的了解,所以請通讀並為自己找到新的東西:) 讓我們開始吧!您需要記住的第一件事是垃圾收集器與您的程序並行工作. 它不是您程序的一部分。它單獨運行(在上一課中,我們將其與機器人真空吸塵器進行了比較)但並非總是如此。過去,垃圾收集是在與您的程序相同的線程上執行的。按照某個時間表(每隔幾分鐘一次),垃圾收集器將檢查程序中是否存在不需要的對象。問題是程序會在檢查和垃圾收集期間掛起(不執行)。想像一下,您正坐在辦公室里工作。但隨後清潔女工進來清洗地板。她讓你離開電腦 5 分鐘,然後你等到她打掃完。在此期間,您無法工作。這就是垃圾收集器過去的工作方式:) 這種機制後來發生了變化,現在垃圾收集器在後台運行,不妨礙程序本身的工作。你已經知道當一個對像不再有引用時它就會死亡。事實上,垃圾收集器不計算對象引用。首先,這可能需要很長時間。其次,它不是很有效。畢竟,對象可以相互引用! 關於垃圾收集器的更多信息 - 2該圖顯示了一個示例,其中 3 個對象相互引用,但沒有其他對象引用它們。換句話說,程序的其餘部分不需要它們。如果垃圾收集器只是簡單地計算引用,這 3 個對象將不會被收集,內存也不會被釋放(它們有引用!)。我們可以將其比作航天器。在飛行過程中,宇航員決定檢查可用於維修的備件清單。除其他外,他們從一輛普通汽車上找到了方向盤和踏板。顯然,這裡不需要它們並且不必要地佔用空間(儘管這兩個部分相互關聯並具有某些功能)。但在飛船內部,它們是應該丟棄的無用垃圾。因此,在 Java 中,決定收集垃圾不是基於引用計數,可達不可達。我們如何確定一個對像是否可達?這一切都非常巧妙。如果一個對像被另一個可達對象引用,則該對像是可達的。因此,我們得到了“可達鏈”。它在程序啟動時開始,並在程序持續期間持續。它看起來像這樣: 關於垃圾收集器的更多信息 - 3 圖中的箭頭表示我們程序的可執行代碼。代碼(例如,main()方法)創建對對象的引用。這些對象可以引用其他對象,這些對象可以引用其他對象,等等。這樣就形成了一個引用鏈. 如果您可以從一個對象追踪到“根引用”(直接在可執行代碼中創建的引用),那麼它就被認為是可達的。此類對像在圖片中標記為黑色。但是如果一個對象掉出這個鏈,那麼這個對象就是不可達的,即當前正在執行的代碼中沒有任何變量引用它,並且不能通過“引用鏈”到達它。在我們的程序中,兩個這樣的對像被標記為紅色。請注意,這些“紅色”對象相互引用。但正如我們之前所說,Java 的現代垃圾收集器不計算引用。判斷一個對像是可達還是不可達. 結果,它會抓住圖中的兩個紅色物體。現在讓我們從頭到尾看一下整個過程。這樣做時,我們還將了解 Java 中的內存是如何安排的:) 所有 Java 對像都存儲在稱為堆的特殊內存區域中。在日常用語中,堆通常是一堆物品,所有東西都混雜在一起。但這不是 Java 中的堆。它的結構非常符合邏輯和合理性。 在某些時候,Java 程序員發現他們所有的對像都可以分為兩種類型:簡單對象“長壽命對象”. “長壽命對象”是在多輪垃圾收集中倖存下來的對象。他們通常會一直活到節目結束。最後,存儲所有對象的完整堆被分成幾個部分。第一部分有一個美麗的名字:伊甸園(來自聖經中的“伊甸園”)。這個名字很合適,因為這是對像在創建後結束的地方。這是我們使用關鍵字 new 時創建新對象的內存部分。可能會創建很多對象。當這個區域空間不足時,初始的“快速”垃圾收集就開始了。不得不說垃圾收集器非常聰明。它根據堆中是否有更多垃圾或更多活動對象來選擇一種算法。如果幾乎所有對像都是垃圾,收集器會標記活動對象並將它們移動到另一個內存區域。那麼當前區域就徹底清空了。如果垃圾不是很多,並且堆中大部分是活動對象,收集器會標記垃圾,將其清除,然後將其他對像打包在一起。我們說 ”一個生存空間一個生存空間,又分為幾代人。每個對像都屬於一個特定的世代,這取決於它在多少輪垃圾收集中倖存下來。如果一個對像在一輪垃圾收集中倖存下來,那麼它就在“第一代”;如果是 5,則為“第 5 代”。eden 和一個生存空間共同組成了一個區域,叫做新生代。除了新生代之外,堆中還有一塊內存區域叫做老年代. 這正是經過多輪垃圾收集後存活下來的長壽命對象所在的區域。將它們與所有其他的分開是有好處的。全量垃圾回收只有在老年代已滿時才執行,即程序中長壽命對象太多,內存不夠用。這一過程涉及多個內存區域。一般來說,它涉及Java機器創建的所有對象。當然,這需要更多的時間和資源。這正是單獨存儲長壽命對象的決定。“快速垃圾回收”是在其他區域空間不足時進行的。這只涉及一個領域,因此速度更快,效率更高。最後,當長壽命對象的區域也被完全填滿時,觸發完整的垃圾收集。因此,收藏家只有在無法避免時才使用“最重”的工具。這是堆結構和垃圾收集的可視化表示: 關於垃圾收集器的更多信息 - 4
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION