jvm優化——圖解垃圾回收,看不懂你捶死我

文末有福利!複製代碼

對於調優以前,咱們必需要了解其運行原理,java 的垃圾收集Garbage Collection 一般被稱爲「GC」,它誕生於1960年 MIT 的 Lisp 語言,通過半個多世紀,目前已經十分紅熟了。所以本篇主要從這三個方面來了解:java

1. 哪些對象須要被回收?python

2. 何時回收?算法

3. 如何回收?bash

1、誰要被回收

java虛擬機在執行java程序的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域,這些區域有各自各自的用途。主要包含如下幾個部分組成:微信

jvm優化——圖解垃圾回收,看不懂你打我

jvm優化——圖解垃圾回收,看不懂你打我

一、程序計數器

程序計數器佔用的內存空間咱們能夠忽略不計,它是每一個線程所執行的字節碼的行號指示器。架構

二、虛擬機棧

java的虛擬機棧是線程私有的,生命週期和線程相同。它描述的是方法執行的內存模型。同時用於存儲局部變量、操做數棧、動態連接、方法出口等。jvm

三、本地方法棧

本地方法棧,相似虛擬機棧,它調用的是是native方法。優化

四、堆

堆是jvm中管理內存中最大一塊。它是被共享,存放對象實例。也被稱爲「gc堆」。垃圾回收的主要管理區域spa

五、方法區

方法區也是共享的內存區域。它主要存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器(jit)編譯後的代碼數據。線程

以上就是jvm在運行時期主要的內存組成,咱們看到常見的內存使用不但存在於堆中,還會存在於其餘區域,雖然堆的管理對程序的管理相當重要,但咱們不能只侷限於這一個區域,特別是當出現內存泄露的時候,咱們除了要排查堆內存的狀況,還得考慮虛擬機棧的以及方法區域的狀況。

知道了要對誰以及哪些區域進行內存管理,我還須要知道何時對這些區域進行垃圾回收。

2、何時回收

在垃圾回收以前,咱們必須肯定的一件事就是對象是否存活?這就牽扯到了判斷對象是否存活的算法了。

引用計數算法

給對象中添加一個引用計數器,每當有一個地方引用它時,計數器+1,當引用失效,計數器-1.任什麼時候刻計數器爲0的對象就是不可能再被使用的。

優勢:實現簡單,斷定效率高效,被actionscript3和python中普遍應用。

缺點:沒法解決對象之間的相互引用問題。java沒有采納

可達性分析算法:

經過一系列稱爲「GC Roots」的對象做爲起始點,從這些節點開始向下搜索,搜索所走過的路徑稱爲引用鏈,當一個對象到GCRoots沒有任何引用鏈相連的時候,則證實此對象是不可用的。

好比以下,右側的對象是到GCRoot時不可達的,能夠斷定爲可回收對象。

jvm優化——圖解垃圾回收,看不懂你打我

在java中,能夠做爲GCRoot的對象包括如下幾種:

* 虛擬機棧中引用的對象。

* 方法區中靜態屬性引用的對象。

* 方法區中常量引用的對象。

* 本地方法中JNI引用的對象。

基於以上,咱們能夠知道,噹噹前對象到GCRoot中不可達時候,即會知足被垃圾回收的可能。

那麼是否是這些對象就非死不可,也不必定,此時只能宣判他們存在於一種「緩刑」的階段,要真正的宣告一個對象死亡。至少要經歷兩次標記:

第一次:對象可達性分析以後,發現沒有與GCRoots相鏈接,此時會被第一次標記並篩選。

第二次:對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過,此時會被認定爲不必執行。

3、如何回收

上述的兩點講解以後,咱們大概明白了,哪些對象會被回收,以及回收的依據是什麼,但回收的這個工做實現起來並不簡單,首先它須要掃描全部的對象,鑑別誰可以被回收,其次在掃描期間須要 」stop the world「 對象能被凍結,否則你剛掃描,他的引用信息有變化,你就等於白作了。

分代回收

咱們從一個object1來講明其在分代垃圾回收算法中的回收軌跡。

一、object1新建,出生於新生代的Eden區域。

jvm優化——圖解垃圾回收,看不懂你打我

二、minor GC,object1 還存活,移動到Fromsuvivor空間,此時還在新生代。

jvm優化——圖解垃圾回收,看不懂你打我

三、minor GC,object1 仍然存活,此時會經過複製算法,將object1移動到ToSuv區域,此時object1的年齡age+1。

jvm優化——圖解垃圾回收,看不懂你打我

四、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象並無達到survivor的一半,因此此時經過複製算法,將fromSuv和Tosuv 區域進行互換,存活的對象被移動到了Tosuv。

jvm優化——圖解垃圾回收,看不懂你打我

五、minor GC,object1 仍然存活,此時survivor中和object1同齡的對象已經達到survivor的一半以上(toSuv的區域已經滿了),object1被移動到了老年代區域。

jvm優化——圖解垃圾回收,看不懂你打我

六、object1存活一段時間後,發現此時object1不可達GcRoots,並且此時老年代空間比率已經超過了閾值,觸發了majorGC(也能夠認爲是fullGC,但具體須要垃圾收集器來聯繫),此時object1被回收了。fullGC會觸發 stop the world。

jvm優化——圖解垃圾回收,看不懂你打我

在以上的新生代中,咱們有提到對象的age,對象存活於survivor狀態下,不會當即晉升爲老生代對象,以免給老生代形成過大的影響,它們必需要知足如下條件才能夠晉升:

一、minor gc 以後,存活於survivor 區域的對象的age會+1,當超過(默認)15的時候,轉移到老年代。

二、動態對象,若是survivor空間中相同年齡全部的對象大小的總和大於survivor空間的一半,年級大於或等於該年級的對象就能夠直接進入老年代。

以上採用分代垃圾收集的思想,對一個對象從存活到死亡所經歷的歷程。期間,在新生代的時刻,會用到複製算法,在老年代時,有可能會用到標記-清楚算法(mark-sweep)算法或者標記-整理算法,這些都是垃圾回收算法基於不一樣區域的實現,咱們看下這幾種回收算法的實現原理。

垃圾回收算法

標記清除法(Mark-Sweep)

標記清除法是垃圾回收算法的思想基礎。標記清除算法將垃圾分爲兩個階段:標記階段和清除階段。

標記階段,經過根節點,標記全部從根節點開始的可達對象,未標記過的對象就是未被引用的垃圾對象。

清除階段,清除全部未被標記的對象。

jvm優化——圖解垃圾回收,看不懂你打我

複製算法(Copying)

複製算法是,將原有的內存空間分爲兩塊,每次只使用其中一塊,在垃圾回收時,將正在適用的內存中存活對象複製到未使用的內存塊,而後清除使用的內存塊中全部的對象。

jvm優化——圖解垃圾回收,看不懂你打我

標記壓縮算法(Mark-Compact)

jvm優化——圖解垃圾回收,看不懂你打我

標記壓縮算法是一種老年代的回收算法。

標記階段和標記清除算法一致,對可達對象作一次標記。

清理階段,爲了不內存碎片產生,將全部的存活對象壓縮到內存的一端。

4、垃圾收集器

垃圾收集器是內存回收的具體實現,不一樣的廠商提供的垃圾收集器有很大的差異,通常的垃圾收集器都會做用於不一樣的分代,須要搭配使用。如下是各類垃圾收集器的組合方式:

jvm優化——圖解垃圾回收,看不懂你打我

jvm優化——圖解垃圾回收,看不懂你打我

微信搜索BGM7756,免費獲取全套架構資料! 


篇幅有限!部分資料圖片以下!


相關文章
相關標籤/搜索