5.一個"小Bug":線程如果不執行呢?
上面說到過現在虛擬機采用的幾乎都是主動式中斷來中斷線程,而其實現又是通過 「線程執行過程中不斷輪詢標志位」 產生自陷異常信號在異常處理表中進行中斷線程,
大家有沒有發現有個小bug:如果我輪詢的操作一直得不到執行呢?這個時候我又該如何讓虛擬機進入垃圾回收狀態。
其實不一定都需要進行中斷線程來保證,回想下STW是為什么:因為如果這個時候用戶線程還在執行的話內存中的引用關系可能會發生變化,所以才需要進行STW。如果一個線程沒有得到CPU時間片執行(java中的線程對應于操作系統的線程,對應關系也可以找筆者之前的關于SignCatcher對線程的理解進行查閱),但是我可以確保其中一部分代碼區域是不會改變內存引用關系的,這樣也可以不用管這些線程。
引入Safe Region(安全區域)解決
?
“安全區域:這部分代碼不會使內存中的引用關系發生變化”,因此只要進入了安全區域,虛擬機就不會管這些線程。當線程離開安全區域后,如果這個時候引用鏈還沒有形成(也就是通過GC Roots遍歷堆內存)那么是不能離開的,一直等待直至引用鏈形成(或者完成了垃圾回收器需要暫停用戶線程的階段)收到信號為止。
?
6. GC Roots會隨著運行時間變長而增加嗎?
基礎知識介紹
根據堆中的不同區域(分代設計)和回收內存空間來判定分為不同的GC名稱:局部回收:Minor GC,MajorGC,..... 整個內存回收:Full GC
如果存在“跨代引用”(最典型的比如老年代對象引用年輕代對象),比如發生Minor GC時,只遍歷普通的GC Roots對象其實結果并不準確( 「某些對象雖然本身不屬于GC Roots但是隨著經歷的GC次數變多成為老年代對象」 ),如果這個時候將這個引用的年輕代對象標記為垃圾清除后,老年代中的對象就會有問題,所以引用鏈形成的過程中還需要 「遍歷整個老年代來保證結果準確」 。
CPU的緩存行技術及偽共享解決方案
!
記憶集
跨域可以理解為跨內存訪問或者訪問其他分代里面的內存
上面遍歷整個老年代這個過程聽起來就很耗時哈哈,事實也確實如此。那么我們可以引入這么一個概念:如果你引用了其他內存里面的對象那么我把你存放到其他內存里面的一個數據結構里面,之后其他內存回收的時候只需要把之前添加到數據結構里面的對象加入到GC Roots中即可。
我們優化一下: 「每個不同的分代中都存著一個數組」 ,這個數組中對堆內存進行一個映射, 我數組中的每一小塊對應的元素是分代中固定大小的內存(比如我第一個數組下標表示我引用的是0到100,第二個數組下標表示引用的是100-200以此類推)。 「當我第一個數組下標對應內存跨域引用了其他分代中的內存,我將把第一個數組下標對應的內存的元素值標識為1代表臟(Dirty)」 ,沒有則為0。當垃圾回收時,我就知道哪部分內存是跨代引用并將他們加入到GC Roots進行掃描(將數組中元素為1對應的內存對象加入GC Roots中)。
根據我映射的內存大小精度又可以進行細分:1.字長精度:只記錄一個機器字長(處理器的尋址位數)該字包含跨代指針
2.對象精度:記錄一個對象(對象字段中含有跨代指針)
3.卡精度:記錄一塊內存區域(該區域有對象包含跨代指針)
最常用的精度
采用“卡精度”的記憶集是通過“卡表”這個數據結構來實現的。
使用精度為卡,這個記憶集的實現方式也被稱為 「卡表」 ,卡表中其實是字節數組結構,每個數組中的元素都對應一部分指定大小內存塊,這部分內存被稱作 「卡頁」 ,當卡頁中的內存塊中引用了其他的內存塊中的一個或多個對象,就會將卡頁中的元素值變為一。變為一的就是臟數據,收集時講這部分內存加入到gc roots中。也就是這樣的:
可能出現的問題
一, 「何時進行更新卡表?」 先看我這張圖哈哈,字不好看,但是大致意思是差不多的。
?
我在寫后屏障中進行更新卡表就可以保證我的卡表記錄是正確的。
?
二, 「“偽共享引起的問題”」 上面剛剛講過CPU的緩存行技術,簡單來說就是如果兩個線程中兩個獨立的變量在同一塊緩存行中,那么不管是哪個線程修改,另外一個線程都需要重新從主存中讀取,而設置緩存行就是為了加快讀取效率,所以這樣勢必會降低效率。
想想剛剛我們記憶集處理方式,如果卡頁對應的內存中發生跨代引用,那么就會對卡表進行更新;上面說的“偽共享”也會在這里出現而且影響性能,比如: 「一個緩存行六十四個字節;一個卡表中的一個元素是一個字節,每個元素對應的一個卡頁存儲的是512字節,也就是一個卡表中64個元素在一個緩存行,而這64個元素對應的總卡頁內存為32KB(64 X 512字節)」 ,如果兩個線程中的變量分配到了這部分內存中,之后變量發生跨代引用更新卡表元素時就會導致另一個線程的緩存行失效而從主存中去拿。所以應該減少更新卡表這個操作,如果已經更新過臟數據了就不需要進行更新卡表了。
-
編程
+關注
關注
88文章
3637瀏覽量
93911 -
GC
+關注
關注
0文章
9瀏覽量
17097 -
JVM
+關注
關注
0文章
158瀏覽量
12252
發布評論請先 登錄
相關推薦
評論