一文講清楚 JVM Safe Point

大家好,我是樹哥。

關於 Safe Point 是 JVM 中很關鍵的一個概念,但我估計有不少同學不是很懂。於是今天跟大家來深入聊聊 Safe Point,希望通過這篇文章能解答這樣幾個問題:

  1. 什麼是 Safe Point?
  2. 爲啥需要 Safe Point?
  3. Safe Point 與 Stop the World 的關係?

什麼是 Safe Point

正如 Safe Point 名稱的寓意一樣,Safe Point 是一個線程可以安全停留在這裏的代碼點。當我們需要進行 GC 操作的時候,JVM 可以讓所有線程在 Safe Point 處停留下來,等到所有線程都停在 Safe Point 處時,就可以進行內存引用分析,從而確定哪些對象是存活的、哪些對象是不存活的。

爲什麼讓大家更加場景化地理解 Safe Point 這個概念,可以設想如下場景:

  1. 當需要 GC 時,需要知道哪些對象還被使用,或者已經不被使用可以回收了,這樣就需要每個線程的對象使用情況。
  2. 對於偏向鎖(Biased Lock),在高併發時想要解除偏置,需要線程狀態還有獲取鎖的線程的精確信息。
  3. 對方法進行即時編譯優化(OSR 棧上替換),或者反優化(bailout 棧上反優化),這需要線程究竟運行到方法的哪裏的信息。

對於上面這些操作,都需要知道現場的各種信息,例如寄存器有什麼內容,堆使用情況等等。在做這些操作的時候,線程需要暫停,等到這些操作完成纔行,否則會有併發問題,這就需要 Safe Point 的存在。

因此,我們可以將 Safe Point 理解成代碼執行過程中的一些特殊位置,當線程執行到這個位置時,線程可以暫停。 Safe Point 處保存了其他位置沒有的一些當前線程信息,可以提供給其他線程讀取,這些信息包括:線程上下文信息,對象的內部指針等。

而 Stop the World 就是所有線程同時進入 Safe Point 並停留在那裏,等待 JVM 進行內存分析掃描,接着進行內存垃圾回收的時間。

爲啥需要 Safe Point

前面我們說到,Safe Point 其實就是一個代碼的特殊位置,在這個位置時線程可以暫停下來。而當我們進行 GC 的時候,所有線程都要進入到 Safe Point 處,纔可以進行內存的分析及垃圾回收。根據這個過程,其實我們可以看到:Safe Point 其實就是柵欄的作用,讓所有線程停下來,否則如果所有線程都在運行的話,JVM 無法進行對象引用的分析,那麼也無法進行垃圾回收了。

此外,另一個重要的 Java 線程特性 —— interrupted 也是根據 Safe Point 實現的。當我們在代碼裏寫入 Thread.interrupt() 時,只有線程運行到 Safe Point 處時才知道是否發生了 interrupted。因此,Safe Point 也承擔了存儲線程通信的功能。

總結

簡單地說,Safe Point 就是人爲規定出的一些代碼位置,在這些位置上線程可以暫停下來,從而讓 JVM 可以進行內存對象引用分析等操作。此外,Safe Point 處也會存儲一些特殊的信息,從而支持 Java 的某些特性,例如:Java 的 interrupt 特性需要到 Safe Point 處才能知道。

其實關於 Safe Point 的內容還有不少,例如:

  1. 什麼地方會放 Safe Point?
  2. Safe Point 具體是怎麼實現的?
  3. 什麼情況會讓所有線程進入 Safe Point?

但對於大多數應用開發人員來說,其實暫時不需要了解得這麼深,只需要知道啥是 Safe Point 以及其存在的價值即可。如果你對這些問題感興趣,可以通過參考資料部分詳細瞭解。

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章