天天看點

jvm學習——20.垃圾回收之安全點與安全區域

162

安全點(Safe point)

  • 程式執行時并非在所有地方都能停頓下來開始GC,隻有在特定的位置才能停頓下來開始GC,這些位置稱為“安全點(Safepoint) ”
  • Safe Point的選擇很重要,如果太少可能導緻GC等待的時間太長,如果太頻繁可能導緻運作時的性能問題。大部分指令的執行時間都非常短暫,通常會根據“是否具有讓程式長時間執行的特征”為标準。比如:選擇些執行時間較長的指令作為Safe Point, 如方法調用、循環跳轉和異常跳轉等。

如何在GC發生時,檢查所有線程都跑到最近的安全點停頓下來呢?

  • 搶先式中斷: (目前沒有虛拟機采用了)

    首先中斷所有線程。如果還有線程不在安全點,就恢複線程,讓線程跑到安全點。

  • 主動式中斷:

    設定一個中斷标志,各個線程運作到Safe Point的時候主動輪詢這個标志,如果中斷标志為真,則将自己進行中斷挂起。

安全區域(Safe Region)

Safepoint機制保證了程式執行時,在不太長的時間内就會遇到可進入GC的Safepoint

但是,程式“不執行”的時候呢?例如線程處于Sleep 狀态或Blocked狀态,這時候線程無法響應JVM的中斷請求,“走” 到安全點去中斷挂起,JVM也不太可能等待線程被喚醒。對于這種情況,就需要安全區域(Safe Region)來解決。

安全區域是指在一段代碼片段中,對象的引用關系不會發生變化,在這個區域中的任何位置開始GC都是安全的。我們也可以把Safe Region 看做是被擴充了的Safepoint。

程式實際執行時:

  1. 當使用者線程運作到Safe Region的代碼時,首先辨別已經進入了Safe Region,如果這段時間内發生GC,JVM會忽略辨別為Safe Region狀态的使用者線程即使用者線程STW,等待JVM執行GC完畢;
  2. 當使用者線程即将離開Safe Region時, 會檢查JVM是否已經完成GC,如果完成了,則使用者線程繼續運作,否則使用者線程必須等待直到收到可以安全離開SafeRegion的信号為止;