以 GC safe-point引入
編寫代碼的時候是能夠知道對象不可用的,但對於程序來講,須要必定的方式來知曉,可用方法好比:編譯分析,引用計數,和對象是否可達html
一個對象只要可以經過mutator觸達,那麼它就是「活」着的。若是Mutator棧的一個槽位包含了對象的引用,那麼對象就是直接可觸達。而從直接可達對象可觸達的對象一定也是可達的,於是可達性分析,只須要找到直接可達的引用。java
直接可達的引用就是根引用,根引用的集合就是根的集合
mutator的上下文就包含了直接可達的數據,因此要獲取對象根集合就是要找到mutator上下文中的對象引用,而mutator的上下文指的就是它的棧、它的寄存器文件以及一些線程上特定的數據安全
全局數據自己也是直接可達的
可達性分析爲了確保能正確的決定對象是否存活,GC須要獲取mutator 上下文的一致性快照,而後枚舉全部的根對象。函數
這裏的一致性指的是 快照的抽取就像只在一個時間點發生,來避免丟失一些活着的對象
一種簡單的方式就是在跟引用的過程當中暫停全部的線程。當mutator暫停了它的執行時,只有將全部引用信息保存在其上下文中,才能枚舉根的集合,這意味着,mutator須要可以告知那些棧的槽位有一用,那些寄存器持有引用。若是GC可以準確的獲取上述引用信息,它就稱做精準根集合枚舉。線程
沒法獲取就是不精準的,如下只講精準的
對於java來講,JIT知曉全部的棧幀信息和寄存器的內容,當JIT編譯一個方法時,對於每條指令,它均可以去保存根引用信息,保存意味着額外的存儲空間,若是要存儲全部的指令就顯得花銷太大,另外在真實的運行過程當中也只有少數指令纔會成爲暫停點,所以JIT只須要保存這些指令點的信息就夠了。而真正有機會成爲暫停點的地方就稱做 safe-points,即可以安全的枚舉根集合的暫停點
。翻譯
「A point in program where the state of execution is known by the VM」,即代碼中VM可以準確知道執行狀態的位置。
safe-point有多個種類code
Hotspot中二者實如今一塊兒,概念上沒有直接聯繫,須要數據不同
當GC想要觸發一次回收時,它會設置一個標誌,mutator則週期性的去檢查(poll)這個標誌,若是檢查到了,就會立馬暫停,這裏的檢查點(poll points)也是安全點,由JIT負責把poll points放到合適的位置htm
polling point插入的主要原則是:對象
權衡下來只在必須和必要的地方加blog
可是有時候並非長時間的執行,而是長時間的空閒,好比 sleep、block,線程在執行其餘的native函數,這些時候JVM沒法掌控執行能力,也就沒法響應GC事件。
不一樣的JVM選用不一樣的位置放置safepoint。
引用safe-region。safe-region是指代碼快中沒有用到會變異的部分,這樣的代碼塊中,任何一個點均可以安全的枚舉根。當進入到safe-region中時,mutator會設置一個準備標記,在離開safe-region區域以前,會檢查GC是否已經完成了回收,若是沒有,那麼就暫停執行,若是有,就能夠直接離開safe-region區域,不須要暫停mutator
代碼的執行過程當中,若是須要執行某些操做,好比GC,deoptimize,等等,必須知道當前程序全部線程運行到的地方,是否可以剛好知足我執行對應操做,而不會對應用程序自己形成損害,這些可以正確執行操做的地方也就是safepoint/saferegion