《深入理解JVM》10-垃圾回收
本系列的第七篇寫過一次垃圾回收,今天看起來優點髒亂差,貽笑大方。這節課是對鄭雨迪老師的課程總結,希望對大家有點幫助。
在第五節的時候我們已經總結過JVM的記憶體設計了
就是上面這張圖,相比大家對這個圖已經熟記於心了,我們知道新生成的物件都會被分配到堆這塊區域,但是隨著系統的不斷執行,堆內的物件越來越多,這個時候就要清理一下,回收無用的物件的記憶體空間,分配給新建立的物件。這就是垃圾回收機制,Java語言能夠如此的風靡有很大一部分原因是JVM自帶了優秀的垃圾回收器,讓開發人員不用關注記憶體空間分配的問題。
死亡物件辨別方法
- 引用計數器演算法
- 可達性分析演算法
最開始的時候,JVM為每個物件提供一個引用計數器,計算指向該物件的引用次數,如果此計數器不為0,表明有使用該物件的其他物件,那麼該物件就是存活的。缺點:記憶體負荷,迴圈依賴,如下圖
為了破解迴圈依賴的問題,jvm優化了演算法,採用可達性分析演算法判斷物件的存活。演算法思想:
- 找到虛擬機器內一組正在被使用的物件,成為GC root
- 從GC root 開始遍歷引用路徑,只要能隨著引用路徑到達的物件,就說明物件存活。
如何確定GC root
- 當前java方法棧棧幀的區域性變數
- 被載入到方法區的類的靜態變數
- JNI handles
- 已啟動未終止的執行緒
缺點,在併發的情況下,可能會誤遍歷不能再到達的物件,比如A執行緒剛執行完,引用的X物件不會被使用了,但是掃描已經標記該物件為可達的。為了確保正確性,JVM引入了Stop The world 和安全點的概念
Stop the world
stop the world 顧名思義,就是要暫停JVM中所有非垃圾回收的工作,直到垃圾回收完成,這個stop the world 會引起服務暫停,也叫GC pause。記憶體分配執行緒發現記憶體不夠用時,會申請JVM進行垃圾回收,提出stop the world請求,虛擬機器會等所有的執行緒進入“安全點”,才允許stop the world進入執行緒獨佔工作。
安全點
安全點不是真正的點,也不是讓執行緒暫停,而是進入一種穩定的狀態,讓GC root不再變動,即JVM的java虛擬機器棧幀不再變動,JNI handles不再變動,只要java方法棧的棧幀不再變動,執行緒還是可以呼叫當前棧幀中的程式碼,即不出現java方法棧入棧出棧操作。執行緒有幾種狀態:
- 解釋執行器執行狀態,逐條解釋執行,可以每條指令檢查安全點
- 即時編譯器執行狀態,只有在方法回邊的時候檢查安全點
- 阻塞狀態:因為java執行緒呼叫在JVM管制範圍內,所以安全
垃圾回收的三種方式
清除:把死亡的物件刪除
壓縮:把死亡的物件刪除,並且移動存活的物件到記憶體一側
複製:把記憶體分為兩部分,每次只用一份,記憶體不夠時,把使用部分的或物件複製到另外一部分記憶體,並清理回收當前記憶體空間
分代思想
物件存活的時間:
根據統計,jvm中的物件按照2-8定律,80%的物件存活的時間極短,只有20%的物件存活的時間很長,所以,80%的物件需要頻繁GC,另外的20%不要,那麼把這兩部分物件分開GC可以獲得更好的GC效果,這就是分代思想。
年輕代:新建立的物件,存放在年輕代
老年代:經歷過預設15次年輕代GC的物件,存放在老年代
年輕代的GC使用的複製方法,把年輕代分為3部分,Eden/Survivor/Survivor三個部分,空間大小8:1:1。
存活的物件被複制到Survivor1區,GC完之後,Survivor1的物件複製到2中,回收Eden和Survivor1,下次GC繼續這麼操作。Survivor區的物件經歷過15次這樣的GC之後,會被移動到老年代。
老年代如果引用了年輕代的物件,在Minor GC的時候,豈不是要遍歷所有的老年代,這不意味著要全堆掃描,為了省略遍歷老年代的時間,引入卡表的概念
卡表:
把對記憶體分為大小相同的區域,每個區域新建一塊卡片,儲存物件引用資訊,那麼就意味著要在所有的寫操作寫入該卡片,JVM引入寫入 屏障 write barrier,這個屏障寫卡片資訊,非常的快。
新生代的垃圾回收器
- Serial :單執行緒的標記-複製
- Paralle Scavenge:跟Parallel差不多,但是更注重吞吐量。不能與CMS共同使用
- Parallel New 多執行緒的標記-複製
老年代垃圾回收器
- Serial Old:單線的標記壓縮
- Parallel Old:多執行緒的標記壓縮
- CMS:標記刪除,隨著G1的發展,CMS在java9之後廢棄
G1回收器
已經打亂了分代的思想,把堆記憶體劃分為多個記憶體區域,每個區域維護一個記憶體分配情況表,當記憶體不夠時,有限回收記憶體中垃圾佔比較大的空間。所以叫Garbage First
相關文章
- 深入理解 JVM 之 垃圾回收機制JVM
- 理解JVM(七):垃圾回收器JVM
- 深入理解JVM——(二)搞定JVM垃圾回收就是這麼簡單JVM
- 深入探究JVM之垃圾回收器JVM
- 深入理解JVM虛擬機器3:垃圾回收器詳解JVM虛擬機
- 從JAVA記憶體到垃圾回收,帶你深入理解JVMJava記憶體JVM
- JVM垃圾回收JVM
- [JVM]垃圾回收JVM
- 深入理解JVM記憶體回收機制(不包含垃圾收集器)JVM記憶體
- JVM垃圾回收概述JVM
- JVM垃圾回收器JVM
- JVM垃圾回收(下)JVM
- JVM - 垃圾回收概述JVM
- 深入理解Go-垃圾回收機制Go
- 深入理解JVM虛擬機器2:JVM垃圾回收基本原理和演算法JVM虛擬機演算法
- JVM 垃圾回收演算法和垃圾回收器JVM演算法
- [效能][JVM]jvm垃圾回收機制JVM
- JVM系列(六) - JVM垃圾回收器JVM
- JVM系列(六) – JVM垃圾回收器JVM
- 深入理解 JVM 之 垃圾收集器JVM
- 深入理解虛擬機器之垃圾回收虛擬機
- 【深入理解Java虛擬機器】垃圾回收Java虛擬機
- JVM-垃圾回收篇JVM
- JVM垃圾回收歷險JVM
- JVM 垃圾回收機制JVM
- jvm 自動垃圾回收JVM
- JVM垃圾回收機制JVM
- 淺談JVM垃圾回收JVM
- JVM 中的垃圾回收JVM
- jvm入門及理解(六)——垃圾回收與演算法JVM演算法
- 深入理解JVM,7種垃圾收集器JVM
- 深入理解JVM(三)——垃圾收集策略詳解JVM
- 深入理解Java虛擬機器 --- 垃圾回收器Java虛擬機
- 再看JVM:垃圾回收那些事JVM
- 淺談JVM與垃圾回收JVM
- 帶你掌握JVM垃圾回收JVM
- 關於JVM的垃圾回收JVM
- JVM垃圾回收演算法JVM演算法