JAVA Stop The World 第八節


JAVA Stop The World 第八節

       小伙伴還記得上一篇中我們留下的一個問題嗎?什么是停頓類型!經過上幾章的學習,我們知道垃圾回收首先是要經過標記的。對象被標記后就會根據不同的區域采用不同的收集方法。看上去很完美的一件事情,其實並不然。

 

       大家有沒有想過一件事情,當虛擬機完成兩次標記后,便確認了可以回收的對象。但是,垃圾回收並不會阻塞我們程序的線程,他是與當前程序並發執行的。所以問題就出在這里,當GC線程標記好了一個對象的時候,此時我們程序的線程又將該對象重新加入了“關系網”中,當執行二次標記的時候,該對象也沒有重寫finalize()方法,因此回收的時候就會回收這個不該回收的對象。

 

        虛擬機的解決方法就是在一些特定指令位置設置一些“安全點”,當程序運行到這些“安全點”的時候就會暫停所有當前運行的線程(Stop The World 所以叫STW),暫停后再找到“GC Roots”進行關系的組建,進而執行標記和清除。

 

 

這些特定的指令位置主要在: 
        1、循環的末尾 
        2、方法臨返回前 / 調用方法的call指令后 
        3、可能拋異常的位置

 

        

        找到“GC Roots”也是要花很長的時間,然而這里又有新的解決方法,就是通過采用一個OopMap的數據結構來記錄系統中存活的“GC Roots”,在類加載完成的時候,虛擬機就把對象內什么偏移量上是什么類型的數據計算出來保存在OopMap,通過解釋OopMap就可以找到堆中的對象,這些對象就是GC Roots。而不需要一個一個的去判斷某個內存位置的值是不是引用。這種方式也叫准確式GC。

 

        回到最開始的問題,那個停頓類型就是剛剛所說的STW,至於有GC和Full GC之分,還有Full GC (System)。個人認為主要是Full GC時STW的時間相對GC來說時間很長,因為Full GC針對整個堆以及永久代的,因此整個GC的范圍大大增加;還有就是他的回收算法就是我們之前說過的“標記--清楚--整理”,這里也會損耗一定的時間。所以我們在優化JVM的時候,減少Full GC的次數也是經常用到的辦法。

 

        本文篇幅較短,為下一章要講的收集器打下基石,各位只要知道GC之前還有STW這一步驟和知道OopMap以及安全點的存在即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM