Java虛擬機之垃圾回收

簡述

Java與那些較傳統的語言好比C++有個很大不一樣就是垃圾回收策略了。前者一般是虛擬機自動幫咱們作了,然後者就須要咱們手動來完成。
Java虛擬機幫咱們完成了垃圾回收,是否是意味着咱們就不用徹底去管它了呢?固然不是的。在不少場景下,虛擬機默認作的並不能使咱們滿意。好比某個java應用較大時,頻繁產生GC,就會很是影響咱們應用的響應速度。這時候就須要咱們根據自身須要,進行相應的調整。那麼如何調整呢?這就須要咱們對虛擬機的垃圾回收機制有所瞭解了。java

找到將要回收的對象

如何找到要回收的對象呢?這裏主要有兩個算法:算法

引用計數法

算法大概思路就是給對象中添加一個引用計數器,每當一個地方引用它時,計數器值就加1;當引用失效時,計數器值就減1;任什麼時候刻計數器值爲0的對象就是不可能再被使用的。
但它的問題在於:很難解決對象之間相互引用的問題。好比對象A引用對象B,同時對象B又引用了對象A,但沒有其餘對象引用這兩個對象,也就是說A和B這個總體是孤立的對象。按理說他們應該是被回收的,可是他們的計數器值並不爲0,因此也就不能被回收了。多線程

可達性分析算法

該算法主要思路就是經過一系列的稱爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走的路徑稱爲引用鏈(Refererce Chain),當一個對象到GC Roots沒有任何引用鏈相連時,則證實此對象時不可用的。下圖爲例,即便對象5和對象六、7相連,但它到GC Roots是不可達的,因此對象五、六、7也是要被回收的。這裏就解決了前面引用計數法所存在的那個問題。因此該算法目前也是大多數商用程序語言的主流實現。
在這裏插入圖片描述併發

垃圾收集算法

垃圾收集算法主要有如下四種,不過基本上後面都是前面的改進或者結合。高併發

標記-清除算法

最基礎的當數「標記-清除」(Mark-Sweep)算法了。算法分兩個階段:「標記」和「清除」。其中「標記」就是找到能夠沒有被引用的對象,「清除」就是收集該對象。以下圖所示(圖片湊合看下吧):
在這裏插入圖片描述
該算法的的缺點很明顯:效率問題空間問題。前者是由於標記和清除兩個過程效率都不高。後者是由於會產生大量不連續的內存碎片,從而致使後續須要分配大對象時找不到足夠的連續空間而提早觸發另外一次收集動做。線程

複製算法

複製(Copying)算法主要時爲了解決前面的效率問題。它將可用的容量分爲大小相等的兩塊,每次只使用其中一塊。其中一塊快用完了,就將存活的對象複製到另一塊上,在把原來那塊使用過的空間清理掉。以下圖所示(顏色有點混了,格子中間水平分爲相等的兩部分)。
主要問題:浪費了太多內存。
目前多數商業虛擬機都採用該算法來回收新生代。但並非嚴格按照1:1的比例分割內存,而是將它分爲一塊較大的Eden空間和兩塊較小的Survivor空間。一塊Eden和一塊Survivor比例大概爲8:1 。每次使用Eden和一塊Survivor空間,回收時將全部存活的對象複製到另一塊未使用的Survivor空間上。
在這裏插入圖片描述3d

標記-整理算法

標記-整理(Mark-Compact)算法,主要適用於對象存活率較高的狀況,而前面的複製算法適用於存活率較低的狀況。算法大概思路就是先標記要回收的對象,而後清除掉掉這些對象,最後將存活的對象複製整理到一塊兒。也就是在前面標記-清除算法的基礎上多了整理的步驟。對象

在這裏插入圖片描述

分代收集算法

分代收集(Generational Collection)算法主要是將內存劃分爲新生代老年代,不一樣塊採用不一樣的算法。新生代對象存活率較低,就採用複製算法;老年代對象存活率較高,就採用標記-整理算法。在這裏插入圖片描述blog

垃圾收集器

在這裏插入圖片描述
垃圾收集器就至關於前面介紹的那些算法的具體實現了。圖片

新生代收集器使用的收集器:Serial、PraNew、Parallel Scavenge

老年代收集器使用的收集器:Serial Old、Parallel Old、CMS

Serial收集器(複製算法)

  新生代單線程收集器,標記和清理都是單線程,優勢是簡單高效。

Serial Old收集器(標記-整理算法)

  老年代單線程收集器,Serial收集器的老年代版本。

ParNew收集器(中止-複製算法) 

  新生代收集器,能夠認爲是Serial收集器的多線程版本,在多核CPU環境下有着比Serial更好的表現。

Parallel Scavenge收集器(中止-複製算法)

  並行收集器,追求高吞吐量,高效利用CPU。吞吐量通常爲99%, 吞吐量= 用戶線程時間/(用戶線程時間+GC線程時間)。適合後臺應用等對交互相應要求不高的場景。

Parallel Old收集器(中止-複製算法)

  Parallel Scavenge收集器的老年代版本,並行收集器,吞吐量優先

CMS(Concurrent Mark Sweep)收集器(標記-清理算法)

  高併發、低停頓,追求最短GC回收停頓時間,cpu佔用比較高,響應時間快,停頓時間短,多核cpu 追求高響應時間的選擇


引用:

《深刻理解Java虛擬機》 第二版 周志明

相關文章
相關標籤/搜索