有關可達性分析的基礎介紹可參看JVM高級特性-三、垃圾收集之判斷對象存活算法中的內容
下面將詳細介紹下再HotSpot中是如何實現的
一、枚舉根節點
問題:
- 在從gc root向下查找引用鏈時,可作為GC ROOT的節點主要在全局性引用(常量、靜態變量)和執行上下文(棧幀中的本地變量表),通常方法區就有數百兆,逐個檢查消耗會很大
- 在查找引用鏈過程中,需要保證引用鏈的一致性,即在分析過程中對象的引用關系不能再變化,否則分析准確性則無法得到保證
因此通常GC執行時會stop the world,停止所有執行線程,即使幾乎不發生停頓的CMS收集器中,枚舉根節點也是需要停頓的。
OopMap:
在HotSpot中,使用的是一種稱為OopMap的數據結構來存儲對象內什么偏移量存儲的是什么類型的數據的映射關系,在JIT編譯
過程中,也會在特定位置記錄下棧和寄存器中的那些位置和引用的,這樣GC在掃描時就可以直接獲得這些信息。
二、安全點(safe point)
概念:
實際上,JVM並非為所有指令都生成OopMap,只是在特定位置記錄這些信息,這些位置就成為安全點。即,程序並非在所
有地方都能停頓下來執行GC,只有在到達安全點時,才可以將線程停頓下來GC。
選定:
安全點的選定通常是以是否能讓程序長時間執行的特征選定的。例如方法調用、執行跳轉、異常跳轉等處。
暫停線程方案:
在GC發生時需要讓線程停頓下來,讓線程停頓下來的方案有兩種,搶先式中斷和主動式中斷
-
-
- 搶先式中斷:
-
在GC發生時先中斷所有線程,如果線程不在安全點上,則啟動該線程使其執行到安全點后掛起。
幾乎已沒有虛擬機只用此種方式
-
-
- 主動式中斷:
-
不需要直接對線程進行操作,在線程執行時主動輪詢這個標識,若中斷標識為真,在線程自己中斷掛起
這個標識和安全點是重合的
三、安全區域(safe region)
上面的安全點檢查仿佛完全解決了如何進入GC的問題,但只有安全點還是不夠的,安全點只解決了那些在運行的程序,保證了他們可以運行到安全點並掛起,但如果有些線程此時並未執行,例如處於sleep或blocked狀態的線程,就無法響應JVM的中斷請求,這是就用到了安全區域
定義:
安全區域是指在此區域內,對象的引用關系不會發生變化(即不會影響枚舉根節點)
原理:
當線程運行到安全區域時會將自己標識,在JVM准備進行GC時將視這些線程為安全的,不影響GC,當線程運行完畢要離開安全區域時,線程會檢查JVM是否在枚舉根節點,若是,則等待完成后再離開安全區域繼續執行。
