枚舉GC Roots
- 在使用可達性分析判斷對象存活時,作爲GC roots的節點主要在全局性的引用(如常量、靜態屬性)與執行上下文(如棧幀中的本地變量表)中,逐個檢查這裏面存在的引用要花費很多時間。
- 可達性分析要求在GC停頓下進行,及在進行可達性分析和GC時必須停頓所有執行線程
- 主流JVM都是使用準確式GC,虛擬機可以直接知道哪些地方存放着對象引用,不需逐個檢查。
- 在hotSpot的實現中,使用一組稱爲OopMap的數據結構來記錄哪些位置是引用,這樣GC在掃描時可以直接得知。
安全點
生成OopMap的位置稱爲安全點,程序執行到安全點則停下來開始GC。安全點的位置一般是程序長時間執行的指令位置,如方法調用、循環跳轉、異常跳轉等。
搶先式中斷和主動式中斷
有兩種方案來實現讓所有線程在GC發生時都運行到最近的安全點上停頓下來:
- 搶先式中斷:在GC發生時,首先把所有線程全部中斷,如果發現有線程中斷的地方不在安全點上,就恢復線程,讓它執行到安全點。
- 主動式中斷:設置一個標誌,各個線程執行時主動去輪詢這個標誌,發現標誌爲真時就自己中斷掛起。這個標誌設置在安全點處以及創建對象需要分配內存的地方。
安全區域
- 安全點機制保證正在執行的程序(即分配了CPU時間的程序)可進入GC的安全點,但對於未分配CPU時間的線程如出於Sleep狀態或Blocked狀態的,由於其無法響應JVM的中斷請求,因而無法執行到安全點再掛起,故安全點機制對其不起作用
- 安全區域是指在一段代碼之中,引用關係不會發生變化,走這個區域中的任意地方開始GC都是安全的。
- 線程執行到安全區域中的代碼時,首先標識自己已經進入了安全區,在這段時間裏JVM要發起GC時,則忽略標識自己爲安全區域狀態的線程。
- 在線程要離開安全區域時,要檢查系統是否已經完成了GC ROOTS,若完成了,線程就繼續執行,否則就必須等待直到收到可以安全離開安全區域的信號爲止。