天天看點

GC回收機制,GC算法。GC垃圾回收

對于java對象,什麼是垃圾狀态呢?就是不再被任何對象所引用.他就是垃圾.

在java中,GC的主要對象是堆空間和永久區。而我們更多讨論的是堆空間這部分。

GC回收機制,GC算法。GC垃圾回收

                   堆的記憶體配置設定圖

jdk8之前有永久代 jdk8之後被取消了,不再有永久代

GC的工作目的很明确:新生成的對象,都放在Eden中;當Eden充滿時(小孩太多 了),GC将開始工作,首先停止應用程式的運作,開始收集垃圾。在堆中,找到已經無用的對象,并把這些對象占用的空間收回使其可以重新利用.大多數垃圾回收的 算法思路都是一緻的:把所有對象組成一個集合,或可以了解為樹狀結構,從樹根開始找,隻要可以找到的都是活動對象,如果找不到,這個對象就是凋零的昨日黃 花,應該被回收了。

垃圾标記算法

我們如何标記一個對象是垃圾呢?主要有幾種方法:引用計數法和可達性分析算法  這兩種屬于垃圾标記算法 并沒有垃圾回收的功能

一.引用計數法的原理:對于一個對象A,隻要有任何一個對象引用了A,則A的引用計數器就加1,當引用失效時,引用計數器就減1。隻要對象A的引用計數器的值為0,則對象A就不可能再被使用。

缺陷:引用和去引用伴随加法和減法,影響性能很難處理循環引用。是以主流java中并沒有使用引用計數法。

二:可達性分析算法:通過判斷對象的引用鍊,來判斷對象是否可以被回收,他是整個程式中 對象所有的引用關系進行搜尋記錄,當GC根連接配接不到的對象,即标記為垃圾對象,如圖灰色即為不可達對象.

什麼對象可以稱為根對象呢,主要有五種

虛拟機棧中引用的對象 方法區中常量引用的對象 方法區中類靜态屬性引用的對象 活躍線程引用的對象,本地方法棧jni(native方法)引用的對象(不熟悉)

GC回收機制,GC算法。GC垃圾回收

垃圾回收算法

我們把對象标記為垃圾對象,接下來就是回收了

一.标記-清除算法是現代垃圾回收算法的思想基礎。标記-清除算法将垃圾回收分為兩個階段:标記階段和清除階段。一種可行的實作是,在标記階段,首先通過根節點,标記所有從根節點開始的可達對象,可達對象可了解為被引用的對象,是以,未被标記的對象就是未被引用的垃圾對象。然後,在清除階段,清除所有未被标記的對象。如圖中,标記階段先标記,清除階段,清除未标記為引用的對象。

簡單說就是标記階段:從跟對象開始掃描,标記存活的對象,清除階段,從堆記憶體進行線性掃描,清除垃圾對象

GC回收機制,GC算法。GC垃圾回收

                           圖1

标記清除算法的缺點:隻清除了不引用的對象,會使那部分對象的空間不連續,造成空間碎片化.

二。複制算法:與标記-清除算法相比,複制算法是一種相對高效的回收方法,不适用于存活對象較多的場合 如老年代。複制算法一般使用在新生代,對新生代進行垃圾回收又叫做MinorGC(他和老年代不沖突)。

複制算法原理:将原有的記憶體空間分為兩塊,分為對象面和空閑面,每次隻使用其中一塊,對象建立在對象面,在垃圾回收時,将正在使用的記憶體中的存活對象複制到未使用的空閑面中,之後,清除對象塊中的所有對象,交換兩個記憶體的角色,完成垃圾回收.

GC回收機制,GC算法。GC垃圾回收

                     圖3

如上圖3,複制算法執行後,先把存活對象複制到另一塊區域,然後對之前區域進行一次清理,第一張圖所畫的A,B空間,把存活的對象由A複制到B,然後清理A區域,再把B區域存活對象複制到A,來回複制,每被複制一次,就會加一計數,當到達十五次(,預設應該是十五次,可以設定)之後,就進入了老年代,如下圖4,還有一部分對象就是大對象,因為占得空間比較大,複制比較占空間,會直接進入老年代。

是以:少量對象存活,适合複制算法。大量對象存活,适合标記清理或者标記整理。

GC回收機制,GC算法。GC垃圾回收

三.标記-壓縮算法(也有的叫标記整理算法)适合用于存活對象較多的場合,如老年代一般使用這種算法,對老年代垃圾回收又叫MajorGC。它在标記-清除算法的基礎上做了一些優化。和标記-清除算法基本思想一樣,标記-壓縮算法也首先需要從根節點開始,對所有可達對象做一次标記。但之後,它并不簡單的清理未标記的對象,而是将所有的存活對象壓縮到記憶體的一端,就是移到一邊。之後,清理邊界外所有的空間。如圖2

GC回收機制,GC算法。GC垃圾回收

                                                              圖二

标記壓縮算法的優點:使用存活率較高的場景,避免記憶體不連續,不用設定兩塊記憶體,造成記憶體浪費

四:分代收集算法(比較主流的垃圾回收算法)

他是按照對象生命周期不同進行劃分,劃分到不同區域,進行不同的算法,是上面算法的一種組合算法

我們經常說哦full GC是其中的一種分類,還有一種是Minor GC

Minor 采用的就是複制算法 

GC回收機制,GC算法。GC垃圾回收
GC回收機制,GC算法。GC垃圾回收
GC回收機制,GC算法。GC垃圾回收

如上圖在新生代中,新建立的對象一般都放在 Eden ,第一次複制 把裡面存活的對象 放進S0 第二次複制,将Eden中&S0中對象,複制到S1,每次對象年齡加1.(S0個S1是新生代兩塊不同于Eden的區域)

什麼時候對象從新生代進入老年代呢?主要有三種

1.預設是15歲之後,2新生代存不下,3超大對象 超過一定size的對象  這三種對象會進入老年代

老年代一般采用标記清理算法和标記整理算法  一般full GC就發生在老年代

full GC通常是堆垃圾回收 觸發點主要有:

1.system.GC  2.老年代空間不足3MInor 去到老年代的對象大小 大于老年代的剩餘空間 4.CMS GC出現異常

補充名詞:

1.Stop-The-World:多半由于GC引起的,Java中一種全局暫停的現象,全局停頓,所有Java代碼停止。native代碼可以執行(但不能和JVM互動)。Jvm處于挂機狀态,當然Dump,線程死鎖檢查,堆Dump,也是有可能引起全局暫停的現象,但多數還是GC引起,原因是GC的時候 ,隻有這個線程執行,其他線程都是等待狀态

2.可觸及的對象:從根節點可以觸及到這個對象。

3.不可觸及的對象:在finalize()調用後,可能會進入不可觸及狀态,不可觸及的對象不可能複活,可以回收。

4.可複活的對象:一旦所有引用被釋放,就是可複活狀态,因為在finalize()中可能複活該對象。

GC時為什麼會有全局停頓?

類比在聚會時打掃房間,聚會時很亂,又有新的垃圾産生,房間永遠打掃不幹淨,隻有讓大家停止活動了,才能将房間打掃幹淨。

JVM運作模式 server client 兩者差別是:client啟動快,運作慢.server啟動慢 運作快 ,server啟動是重量級的虛拟機,運作要快

注意事項:

1.當eden滿了,觸發young GC;

2.young GC做2件事:一,去掉一部分沒用的object;二,把老的還被引用的object發到survior裡面,等下幾次GC以後,survivor再放到old裡面。

3.當老年代滿了,觸發full GC。full GC很消耗記憶體,把old,young裡面大部分垃圾回收掉。這個時候使用者線程都會被block。

4.young generation比例越大,不一定最好。将young的大小設定為大于總堆大小的一半時會造成效率低下。如果設定得過小,又會因為young generation收集程式不得不頻繁運作而造成瓶頸。

5.在sun 的文檔說明中,對JVM堆的新域,是采用coping算法,該算法的提出是為了克服句柄的開銷和解決堆碎片的垃圾回收。

看完算法,并不能學會如何優化jvm參數,感覺隻是入門嘗試

http://www.importnew.com/3146.html