摘要:當暫停了它的執行時,只有將所有引用信息保存在其上下文中,才能枚舉根的集合,這意味著,需要能夠告知那些棧的槽位有一用,那些寄存器持有引用。而真正有機會成為暫停點的地方就稱作,即能夠安全的枚舉根集合的暫停點。
以 GC safe-point引入GC如何找到不可用的對象
編寫代碼的時候是可以知道對象不可用的,但對于程序來說,需要一定的方式來知曉,可用方法比如:編譯分析,引用計數,和對象是否可達
可達性分析一個對象只要能夠通過mutator觸達,那么它就是“活”著的。如果Mutator棧的一個槽位包含了對象的引用,那么對象就是直接可觸達。而從直接可達對象可觸達的對象必定也是可達的,因而可達性分析,只需要找到直接可達的引用。
直接可達的引用就是根引用,根引用的集合就是根的集合
mutator的上下文就包含了直接可達的數據,所以要獲取對象根集合就是要找到mutator上下文中的對象引用,而mutator的上下文指的就是它的棧、它的寄存器文件以及一些線程上特定的數據
全局數據本身也是直接可達的
可達性分析為了確保能正確的決定對象是否存活,GC需要獲取mutator 上下文的一致性快照,然后枚舉所有的根對象。
這里的一致性指的是 快照的抽取就像只在一個時間點發生,來避免丟失一些活著的對象如何獲取 mutator上下文的一致性快照
一種簡單的方式就是在跟引用的過程中暫停所有的線程。當mutator暫停了它的執行時,只有將所有引用信息保存在其上下文中,才能枚舉根的集合,這意味著,mutator需要能夠告知那些棧的槽位有一用,那些寄存器持有引用。如果GC能夠準確的獲取上述引用信息,它就稱作精準根集合枚舉。
無法獲取就是不精準的,以下只講精準的如何獲取精準的引用信息枚舉
對于java來說,JIT知曉所有的棧幀信息和寄存器的內容,當JIT編譯一個方法時,對于每條指令,它都可以去保存根引用信息,保存意味著額外的存儲空間,如果要存儲所有的指令就顯得花銷太大,另外在真實的運行過程中也只有少數指令才會成為暫停點,因此JIT只需要保存這些指令點的信息就夠了。而真正有機會成為暫停點的地方就稱作 safe-points,即能夠安全的枚舉根集合的暫停點。
safe-point 定義“A point in program where the state of execution is known by the VM”,即代碼中VM能夠準確知道執行狀態的位置。
safe-point有多個種類
GC safepoint,要觸發一次GC,JVM中的所有線程都必須達到GC safepoint
Deoptimization safepoint,要觸發一次 deoptimization,需要執行deoptimization的線程要到達safepoint之后才可以開始deoptimize
Hotspot中兩者實現在一起,概念上沒有直接聯系,需要數據不一樣如何保證mutator會在 safe-point暫停
當GC想要觸發一次回收時,它會設置一個標志,mutator則周期性的去檢查(poll)這個標志,如果檢查到了,就會立馬暫停,這里的檢查點(poll points)也是安全點,由JIT負責把poll points放到合適的位置
那些地方適合設置檢查GC事件的標記polling point插入的主要原則是:
polling point應該足夠多,防止GC等一個mutator的暫停太長,導致其他mutator都走在等GC釋放空間,程序整個等待過長
polling point不能太頻繁導致運行時存儲開銷過大
polling本身也是有開銷的,不能過多
權衡下來只在必須和必要的地方加
在分配地址的時候強制添加,因為分配空間很有肯能導致回收,所以這里是一個安全點
長時間的執行一般意味著循環和方法調用,所以方法調用和循環返回最好加上
但是有時候并不是長時間的執行,而是長時間的空閑,比如 sleep、block,線程在執行其他的native函數,這些時候JVM無法掌控執行能力,也就無法響應GC事件。
不同的JVM選用不同的位置放置safepoint。如何解決sleep/block 帶來的問題
引用safe-region。safe-region是指代碼快中沒有用到會變異的部分,這樣的代碼塊中,任何一個點都可以安全的枚舉根。當進入到safe-region中時,mutator會設置一個準備標記,在離開safe-region區域之前,會檢查GC是否已經完成了回收,如果沒有,那么就暫停執行,如果有,就可以直接離開safe-region區域,不需要暫停mutator
文章翻譯自 Xiao-Feng Li 博客
rednaxelafx對safepoint的回答
總結代碼的執行過程中,如果需要執行某些操作,比如GC,deoptimize,等等,必須知道當前程序所有線程運行到的地方,是否能夠恰好滿足我執行對應操作,而不會對應用程序本身造成損害,這些能夠正確執行操作的地方也就是safepoint/saferegion
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72725.html
摘要:線程安全的概念什么時候線程不安全怎樣做到線程安全怎么擴展線程安全的類對線程安全的支持對線程安全支持有哪些中的線程池的使用與中線程池的生命周期與線程中斷中的鎖中常見死鎖與活鎖的實例線程同步機制顯示鎖使用與原理原理剖析原理中的與原理偏向鎖狀態 showImg(https://segmentfault.com/img/bVblUE9?w=1354&h=1660); 線程安全的概念 showI...
摘要:這個算法看似不錯而且簡單,不過存在這一個致命傷當兩個對象互相引用的時候,就永遠不會被回收于是引用計數算法就永遠回收不了這兩個對象,下面介紹另一種算法。 前言 ? 如果要問Java與其他編程語言最大的不同是什么,我第一個想到的一定就是Java所運行的JVM所自帶的自動垃圾回收機制,以下是我學習JVM垃圾回收機制整理的筆記,希望能對讀者有一些幫助。 哪些內存需要回收?what? ? ...
摘要:線程安全需求分析三個例子都是關于車輛追蹤的。他們使用了不同的方式來保證車輛追蹤類的線程安全性。值得注意的值文檔也是維護線程安全的重要組成部分。 每個例子后面有代碼,大家可以先把代碼粘出來或者開兩個頁面,先過一下例子的代碼,然后一邊看分析一遍看代碼,上下拖動看的話效果不好。 歡迎拍磚和補充。 線程安全需求分析 三個例子都是關于車輛追蹤的。他們使用了不同的方式來保證車輛追蹤類的線程安全性。...
摘要:然而對于一個和關聯的線程來說在線程被創建和更新他的之前會有一個小窗口,因此必須檢查這種情況為線程結構體分配內存并創建線程。可能是,因此我們耗盡了內存太多的活躍線程。代碼執行到這,線程還是狀態,因為線程必須被創建者直接啟動。 引言 說到Thread大家都很熟悉,我們平常寫并發代碼的時候都會接觸到,那么我們來看看下面這段代碼是如何初始化以及執行的呢? public class Thread...
摘要:前言本文是一篇簡短的雜糅本文源自于作者最近的一個疑問為什么在舊版的中偏向鎖的移除一定要在全局安全點進行同時在上個星期作者參與的一個項目發生了一件怪事一個服務莫名其妙地不接受任何請求了一切請求都是而查看日志發現出故障的服務本身去請求另一個服務 前言 本文是一篇簡短的雜糅. 本文源自于作者最近的一個疑問:為什么在舊版的jdk中偏向鎖的移除一定要在全局安全點進行?同時在上個星期,作者參與的一...
閱讀 2955·2021-10-20 13:46
閱讀 2511·2021-08-12 13:22
閱讀 2692·2019-08-30 15:54
閱讀 2336·2019-08-30 15:53
閱讀 540·2019-08-30 13:47
閱讀 3574·2019-08-23 16:56
閱讀 1720·2019-08-23 13:02
閱讀 1790·2019-08-23 12:25