JavaRush /Java Blog /Random-TW /有關 Java 中垃圾收集器的更多信息

有關 Java 中垃圾收集器的更多信息

在 Random-TW 群組發布
你好!上一講,我們首先熟悉了Java語言的內建機制—垃圾收集器。當您的程式運行時,它在背景運行,收集不再需要的對象,這些對象稍後將被刪除。這樣它就可以釋放記憶體以供將來建立新物件。在本次講座中,我們將仔細研究其工作原理。例如,某個物件如何以及在什麼時候變得不再需要?垃圾收集器如何知道這一點?我們將回答這些問題:)我們的講座更多的是概述:這些材料不需要記住。它的目的是拓寬您對記憶體和垃圾收集器工作的視野,因此閱讀它並為自己學習新東西就足夠了:) 讓我們開始吧!您需要記住的第一件事是垃圾收集器與您的程式並行運行。它不是它的一部分,而是單獨發揮作用:為了描述這一點,在上一講中我們用機器人吸塵器進行了類比。事實上,情況並非總是如此。以前,垃圾收集器的設計方式是它與程式在同一線程中工作。根據某個時間表,它每隔幾分鐘就開始檢查程式中是否存在不必要的物件。問題是,在這次檢查和垃圾收集期間,程式凍結並且沒有執行。想像一下您正坐在辦公室工作。但後來一位清潔女工來了,需要清洗房間裡的地板。她把你從電腦後面踢了 5 分鐘,你等她打掃完。在此期間您無法工作。這大致就是垃圾收集器過去的工作方式:)後來,這種機制被改變了,現在垃圾收集器在後台工作,不會減慢程式本身的工作速度。您已經知道,當一個物件不再有任何引用時,該物件就會死亡。但垃圾收集器其實不計算對. 首先,它可能會很長。其次,效果不太好。畢竟,物件可以互相引用! 有關垃圾收集器的更多資訊 - 2該圖顯示了一個範例,其中 3 個物件相互引用,但沒有其他物件引用它們。也就是說,程式的其餘部分不需要它們來運行。如果垃圾收集器只是簡單地計算引用,那麼所有這 3 個物件都將保留並且不會釋放記憶體:有對它們的引用!它可以比喻為一艘太空船。在飛行過程中,太空人決定檢查維修備件清單,並在其中發現了一輛普通汽車的方向盤和踏板。顯然這裡不需要它們並且佔用額外的空間。雖然這些部件是相互連接的並且具有一定的功能,但在航天器運行的框架內它們是不必要的垃圾,最好扔掉。因此,Java決定讓垃圾回收的基礎不計數引用,而是將物件分為兩種類型—可達不可達。如何判斷一個物件是否可達?一切巧妙的事情都很簡單。如果一個物件被另一個可達物件引用,則該物件是可達的。這導致了“可達鏈”。它在程式啟動時啟動,並在其整個運行期間持續進行。看起來像這樣: 有關垃圾收集器的更多資訊 - 4圖中的箭頭表示我們程式的執行程式碼。在程式碼中,例如在 main() 方法中,建立對物件的參考。這些對象可以引用新對象,也可以引用更多對象,等等。形成了物件連結鏈。如果可以透過此連結鏈到達「根連結」(即在執行程式碼中直接建立的連結),則該物件被認為是可達的。在我們的圖片中,它們以藍色表示。但如果一個物件脫離了這條鏈,即當前正在執行的程式碼中沒有一個變數包含對它的引用,也無法透過「連結鏈」到達它——它被認為是不可達的。在我們的程式中,兩個這樣的物件以紅色表示。請注意:這些「紅色」物件相互之間有連結。但是,正如我們之前所說,Java 中的現代垃圾收集器不進行引用計數。它確定物件是否可達不可達。因此,畫面中的兩個紅色物體就會成為他的獵物。現在讓我們從頭到尾看一下整個過程,同時讓我們看看Java中記憶體是如何運作的:) Java中的所有物件都儲存在一個稱為堆的特殊記憶體區域中。用普通語言來說,「堆」是指堆積如山的物體,其中所有東西都亂七八糟地散落在各處。但Java中的堆卻不是這樣的。它的結構非常有邏輯性和合理性。有一天,Java 程式設計師發現他們程式中的所有物件都可以分為兩種類型 - 相對而言,簡單物件「長壽」物件。「長壽」對像是那些在多次垃圾回收中倖存下來的對象。大多數情況下,它們將一直存在到程式結束。結果,儲存所有建立的物件的公共堆被分成幾個部分。第一部分有一個美麗的名字-Eden 聖經中的「伊甸園」)。這是一個很棒的名字,因為這是物件創建後的位置。當我們寫入時,正是在這一部分為新物件分配內存new。可以創建許多對象,當該區域的空間耗盡時,第一個「快速」垃圾收集開始。必須說,垃圾收集器非常聰明,它根據堆中更多的內容(垃圾或工作對象)來選擇工作演算法。如果幾乎所有物件都是垃圾,則收集器會標記「活動」物件並將它們移動到另一個記憶體區域,然後將當前區域完全清理乾淨。如果垃圾很少,並且大部分被活體佔據,它就會標記垃圾,清理它,並安排剩餘的物件。我們說“收集器標記“活動”物件並將它們移動到另一個記憶體位置”,但是哪一個呢?至少在一次垃圾回收中倖存下來的所有物件都被轉移的記憶體區域稱為「生存空間」生存空間又分為世代。每個物件都會根據其經歷的垃圾回收次數分配一個世代。如果有一個,則屬於“第一代”,如果有 5 個,則屬於“第五代”。伊甸園和生存空間一起形成一個稱為年輕一代的區域。除了Young Generation之外,堆中還有另一個記憶體區域-Old Generation(「老年代」)。這些是在多次垃圾回收中倖存下來的非常長壽的對象。將它們與其他所有東西分開存放會更有利可圖。並且只有當老一代區域已滿時,即 即使程式中存在如此多的長壽命對象,導致記憶體不足,也會執行完整的垃圾收集。它不僅處理一個記憶體區域,而且通常處理 Java 機器創建的所有物件。當然,這需要更多的時間和資源。這就是為什麼決定單獨儲存長壽命物件的原因。當其他區域的空間耗盡時,就會進行所謂的「快速垃圾收集」。它只覆蓋一個區域,因此更經濟、更快。最後,當百歲老人的區域也已經堵塞時,徹底的清理工作就開始了。因此,只有當不再需要時,組裝人員才會使用最「重」的工具。示意性地講,堆和清理的結構如下圖所示: 有關垃圾收集器的更多資訊 - 5
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION