天天看點

JVM深入學習筆記四:JVM垃圾收集和記憶體配置設定

1. 垃圾判斷算法

引用計數法,    給對象添加引用計數器,每有一個引用則+1, 沒有則-1,為0為已死。python就是使用這種算法。  但是不能解決循環引用的問題。

根搜尋算法。     從根開始向下搜尋,如果有對象到根不可達則為死對象。 hopspot使用的是這種算法。  

這裡的根可以是棧中的引用對象, 方法區常量的引用對象,方法區靜态屬性的引用對象,jni的引用對象。

兩次标記。   虛拟機在回收對象時要做兩次标記才會真的回收。無根的時候是一次,執行了finallise方法的時候會再标記一次。标記兩次後,再執行到finalise方法就會回收對象。

回收方法區。 會回收常量池和做類解除安裝,可以使用-verbose:class來檢視類的裝載及解除安裝情況。

2. 垃圾收集算法

标記清除算法。

标記出所有需要回收的對象,标記完成後清除所有标記了的對象。   問題在于:效率不高,空間上會産生大量的碎片

複制算法。

把記憶體分為兩個等塊, 每次使用一塊,當這一塊滿了之後把存活的對象轉移到另外一塊上去,然後清空這一塊。  這樣有點空間浪費。

hopspot 的新生代基于這個算法,把記憶體分為了一個較大的eden空間和兩個較小的survior空間。每次使用eden和一個survior,gc的時候把他們兩個中存活的對象拷貝到另一個s空間,清空eden和s1, 如果s2不夠大,則會把對象複制到老生代。

标記整理                  當系統運作比較久後,對象的存活率比較高,複制算法就會有很多的複制操作,效率将會變低。是以對于老生代,使用标記-真理算法。

把存活對象标記并向一個方向清理,完成後把邊界外的統一清空。

基于複制算法的新生代,标記整理的老生代,也就是分代收集的算法了。新生代gc(minor gc), 老生代gc(major gc)

3. 垃圾收集器

有很多種,主要是針對問題的不同,有單線程的,為了減少停頓時間的,還有使用不同算法實作的。 目前最新的叫做g1

4. 記憶體配置設定

優先在eden上配置設定

參數:

-verbose:gc 列印gc的資訊

-xmn:新生代大小

-xx:sur... : eden和s的比

-xx:+print.. : 列印詳細的gc資訊

代碼:

輸出:

大概的過程是,前三個對象配置設定在eden上,當配置設定第四個的時候發現eden不夠大, 是以做gc,做gc的時候發現對象都比s大,是以配置設定到老生代去了。

最後将是eden上對象4,  老生代上有1,2,3

大對象直接進入老生代

上面那個例子,加入參數-xx:pertenuresizethreshold參數指定大于這個值的對象會直接進入老生代。

長期存活的對象将進入老生代

每熬過一次minorgc年齡增加一歲,  -xx:maxtenuringthreshold設定幾歲的對象進入老生代。

大于平均值的進入老生代

當處于一個年齡的對象達到了數目的一半以上,那麼比這個年齡大的将會進入到老生代。