您好,登錄后才能下訂單哦!
這期內容當中小編將會給大家帶來有關GC是怎么快速枚舉根節點的,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Java一個優點就是GC(Garbage Collection),雖然它能幫我們管理內存,但是它工作的時候會STW(Stop the World)。也就是停止所有的工作線程,"你們先別干活,我先來清理清理垃圾!"。
那就出問題了啊,你想想比如你在玩游戲的時候,電腦來個STW停個幾秒鐘時間,清理下垃圾。你可能就會"****",你隊友可能也會"***"。
但是現在常用的一些垃圾收集器都得STW,雖然各種垃圾收集器已經各種絞盡腦汁減少STW的時間,但是做不到避免STW。具體的各種垃圾收集器的對比下次單獨寫一篇文章。
今天先來講述一下GC是如何快速枚舉根節點。在HotSpot虛擬機中,是通過可達性分析來判斷此對象是否需要回收的。那可達性分析就需要找到“源頭”,也就是根節點。
通過枚舉一個一個根節點(GC Roots),然后順藤摸瓜一路摸下來,然后沒摸到的那些對象就把它咔嚓回收了。那這個順藤摸瓜的過程就必須讓世界停止,也就是那些工作線程都得停了。
你想想如果不STW那對象引用關系變來變去的,垃圾收集器得怎么咔嚓對象啊,容易咔嚓錯了,那咱們使用者不就急眼了啊。所以枚舉根節點時STW不可避免,所以只能讓STW盡量的短。
根節點主要在全局性的引用(常量、類靜態屬性)和執行上下文(棧幀中的本地變量表)中。那我們如果要一個一個的找過去就很慢。
并且我們的HotSpot又是準確性GC,也就是它需要知道某個位置上的某個數據的類型,類型是準確的。這樣它就能準確的知道這塊數據類型是不是它關心的指針也就是引用啦!
在HotSpot中是用了一種叫OopMap的結構來存放一個對象內什么偏移量上是什么類型的數據。在類加載過程中就會進行記錄。
可以把OopMap理解為一個附加信息,或者說一件衣服的吊牌,咱們看吊牌就知道這衣服啥做的。所以GC在掃描的時候就可以直接看這些“吊牌”來知道信息了。
在JIT編譯的時候也會在一些特定的位置記錄下OopMap,記錄了執行到該方法的某條指令的時候,棧上和寄存器里哪些位置是引用,每個方法可能會有好多個OopMap,這是根據特定位置來決定的,這個特定位置會把這個方法分會好幾塊,每一塊都有一個OopMap。
這些特定的位置主要在:
1、方法臨返回前/調用方法的call指令后
2、循環的末尾
3、可能拋出異常的地方
這些特定的位置也叫安全點(Safepoint)。
之所以要在特定的位置才記錄OopMap,是因為如果對每條指令都記錄一下的話,那就會需要大量的空間,提高了GC的空間成本,所以用一些比較關鍵的點來記錄就能有效的縮小記錄所需的空間。
因此GC不是隨時隨地來的,得到達安全點時才可以開始GC。
平時OopMap是壓縮在內存中,只要當要GC的時候才會解壓出來,然后開始遍歷來掃描對應的偏移量。
對于JNI(Java Native Interface)方法,因為本地方法和解釋器、JIT編譯器沒啥關系,所以就沒有OopMap。
它的引用是加了個中間層一樣的,就是句柄,也就是引用不是直接指向堆中的對象,而是引用指向句柄,句柄指向堆中對象。所以GC直接掃描句柄就行了,不需要掃描棧幀。
上述就是小編為大家分享的GC是怎么快速枚舉根節點的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。