2011-12-12 309 views
7

我最近閱讀了關於垃圾回收的一些小部分(大部分是用Java編寫的),有一個問題仍然沒有答案:JVM(或者一般的運行時系統)如何跟蹤當前的活動對象?垃圾回收 - 根節點

我知道那裏的對象是當前在堆棧中的對象,所以所有的局部變量或函數參數都是ARE對象。這個問題的解決方法是,無論何時運行時系統檢查堆棧中當前是什麼,它將如何區分參考變量和簡單的int?它不能,可以嗎?

因此,必須有某種機制,以允許在運行時建立活動對象初步名單以通爲標誌掃描階段的...

回答

4

我發現greyfairer提供的答案是錯誤的。 JVM運行時不會通過查看用於在堆棧上推送數據的字節碼來收集堆棧的根集。堆棧幀由4個字節(32位拱)插槽組成。每個插槽可以是對堆對象的引用或像int這樣的原始值。當需要GC時,運行時從上到下掃描堆棧。對於每個插槽,如果包含參考文件:

a。它在4字節的邊界對齊。

b。插槽中的值指向堆的區域(在下限和上限之間)。

c。 allocbit已設置。 allocbit是一個標誌,表示與其對應的內存位置是否被分配。

這裏是我的參考:http://www.ibm.com/developerworks/ibm/library/i-garbage2/

還有一些其他技術可以找到根集(而不是Java)。例如,因爲指針通常在4/8字節邊界處對齊,所以第一位可以用來指示一個時隙是基元值還是指針:對於基元值,第一位設置爲1.缺點是你只有31位(32位拱)來表示整數,並且對原始值的每個操作都涉及移位,這顯然是一個開銷。

此外,您可以使所有類型包括int分配在堆上。也就是說,所有的東西都是物體。然後,堆棧幀中的所有槽都是引用。

+0

因此,總而言之,它是相當低層次的差異化,而不是JVM?但JVM有一個爲字節碼聲明的引用類型,所以爲什麼不使用它呢?您確定它的級別如此之低,而不是字節代碼級別? – Bober02

+1

據我所知(基於我之前給出的鏈接以及瀏覽幾個JVM實現的代碼),我相信我的理解是正確的。您可以簡單地深入一些開源JVM實現的GC代碼來檢查這一點。他們都需要走棧以找出參考。但是,也許用於驗證插槽是否爲引用的標準略有不同(大多數驗證a。和b。對於c,它實際上是基於實現的)。 – Rainfield

+0

爲什麼不使用字節碼,這是我的理解(不知道它是否正確)。 GC是一個運行時間的東西,但字節碼是在編譯時和靜態時生成的。當GC發生時,運行時系統需要找出根並跟蹤它們以找出活動對象。 。要做到這一點,你必須實際檢查每個堆棧幀的值,即使你知道這個槽在編譯時包含一個引用(正如greyfairer所說,通過查看字節碼你可以知道這一點)。因爲您需要知道確切的參考值才能找到堆中的其他對象。 – Rainfield

2

運行時可以參考的變量和原語之間的完美區分,因爲這是在編譯的字節碼中。例如,如果一個函數f1調用一個函數f2(int i,Object o,long l),調用函數f1將在表示i,4(或8?)的堆棧(或寄存器)上推4個字節。 )爲o的引用字節,l爲8個字節。被調用的函數f2知道堆棧中哪些位置可以找到這些字節,並且可能會將引用複製到堆上的某個對象。當函數f2返回時,調用函數將從堆棧中刪除參數。

運行時解釋字節碼並記錄它在堆棧上壓入或下落的內容,因此它知道什麼是引用,什麼是原始值。

根據http://www.javacoffeebreak.com/articles/thinkinginjava/abitaboutgarbagecollection.html,java使用tracing garbage collector而不是引用計數算法。

+0

謝謝你的回答。考慮到這一點,垃圾收集在JVM啓動時如何進行?它如何實際定位根節點 - 跳回堆棧,還是有單獨的節點集合? – Bober02

+0

查看文章鏈接進行深入解剖。 – greyfairer

+0

我在您引用的文章中找到以下句子'標記和掃描遵循從堆棧和靜態存儲開始並通過所有句柄跟蹤來查找活動對象的相同邏輯。'這些神祕的手柄是指什麼...... – Bober02

0

HotSpot VM爲編譯的每個子例程生成GC映射,其中包含有關根的位置的信息。例如,假設它已經編寫了子程序機器代碼(其原理是字節代碼相同),這是120個字節長,那麼它的GC地圖可能是這個樣子:

0 : [RAX, RBX] 
4 : [RAX, [RSP+0]] 
10 : [RBX, RSI, [RSP+0]] 
... 
120 : [[RSP+0],[RSP+8]] 

這裏[RSP+x]是應該指示堆棧位置和R??寄存器。因此,如果線程在偏移10的彙編指令處停止並且運行gc循環,則HotSpot知道三個根在RBX,RSI[RSP+0]。它跟蹤這些根,並在必須移動對象時更新指針。

我爲GC圖描述的格式只是爲了演示原理,顯然不是一個HotSpot實際使用的格式。它並不完整,因爲它沒有包含關於包含原始活動值的寄存器和堆棧槽的信息,並且對於每個指令偏移量使用列表都沒有空間效率。您可以通過多種方式以更高效的方式打包信息。