JVM的垃圾回收算法

JVM的垃圾回收算法java

一,如何判斷對象已經消亡算法

1,引用計數算法數組

一個對象若是沒有任何引用指向它,就可認爲該對象已經」消亡「,這種方法有個缺點就是沒法檢測到引用環的存在。安全

算法特色ide

1. 須要單獨的字段存儲計數器,增長了存儲空間的開銷;spa

2. 每次賦值都須要更新計數器,增長了時間開銷;對象

3. 垃圾對象便於辨識,只要計數器爲0,就可做爲垃圾回收;blog

4. 及時回收垃圾,沒有延遲性;生命週期

5. 不能解決循環引用的問題;內存

2,根搜索算法

Java使用根搜索算法回收垃圾,該算法的基本原理:定義一系列名爲GC Roots的對象做爲起點,從起點向下搜索,搜索所走過的路徑稱爲引用鏈。

當一個對象到GC Roots沒有任何引用鏈相連,則說明該對象不可用,這時Java虛擬機能夠對這些對象進行回收。

Java虛擬機將如下對象定義爲 GC Roots

1), Java虛擬機棧中引用的對象:好比方法裏面定義這種局部變量 User user= new User();

2),靜態屬性引用的對象:好比 private static User user = new User();

3),常量引用的對象:好比 private static final  User user = new User();

4),本地方法棧中引用的對象

二,經常使用的垃圾回收算法

1,標記-清除算法。

該算法包含標記和清楚兩個階段:

首先是標記處全部須要回收的垃圾對象,標記完成以後統一進行回收處理。

該算法主要不足:

A),一個是效率問題。標記和清楚兩個過程的效率都不高。

B),一個是空間的問題。標記清楚以後會致使大量不連續的內存碎片。空間碎片過多會致使在程序運行過程當中須要分片大量內存的時候沒法找到知足連續內存而不得不提早出發另外一次垃圾回收動做。標記-清除算法的執行過程以下圖:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

2,複製算法

此算法把內存劃分爲相等大小的兩個區域,每一隻使用其中一個,回收過程當中將存活的對象所有複製到另外一個區域中,清空原區域。在年輕代中eden區和兩個survivor區就是使用了此種算法。這種算法只複製存活的對象,成本較低,並且不會出現內存碎片問題,缺點是須要2倍的內存空間。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

3,標記整理算法

複製收集算法在對象存活率較高的時候就要進行較多的複製操做,效率將會變的很低。更關鍵是,若是你不想浪費一半內存空間,就須要有額外的內存空間進行分配擔保,以應對被使用的內存中全部對象都100%存活的極端狀況,因此老年代不採用這種算法。

根據老年代的特色,有人提出了另一種標記-整理算法,標記過程仍然與標記清除算法同樣,而後直接清理掉端邊界之外的內存,標記-整理算法的示意圖以下:

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

4,分代回收算法

當前商業虛擬機的垃圾回收器都採用分代收集算法,這種算法並無什麼新的思想,只是根據對象存活週期的不一樣將內存花費爲幾塊。通常是把java堆分爲新生代和老年代,這樣就能夠根據各個年代的特色採用最適當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,只有少許存活,那就選用複製算法,只須要付出少許存活對象的複製陳本就能夠完成收集。而老年代中由於對象存活率高,沒有額外空間對它進行分配擔保,就必須使用標記清除或者標記整理算法來進行垃圾回收。

三,內存分配和回收的策略

目前JVM分代主要是分三個年代:

新生代:全部新建立的對象都首先在新生代進行內存分配。新生代具體又分爲3個區,一個Eden區、一個From Survivor區和一個To Sruvivor區。大部分對象都被分配在Eden區,當Eden區滿時,還存活的對象將被複制到From Survivor區,當From Survivor區滿時,此區還存活的對象將被複制到To Survivor區。最後,當To Survivor區也滿時,這時從From Survivor區複製過來而且還存活的對象將被複制到老年代。

老年代:在年輕代中經歷了N次(通常是15次)GC後依然存活的對象,就會被放到老年代當中。所以,能夠認爲老年代是存放一些生命週期較長的對象。

持久代:用於存放靜態文件,如Java類等。

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

GC的種類:

新生代GC(Minor GC):

指的是發生在新生代的垃圾收集動做,由於Java對象大多都具有朝生夕滅的特性,因此MinorGC很是頻繁,通常回收速度也比較快。

老年代GC(MajorGC/FullGC):

指發生在老年代的GC,出現了MajorGC,常常會伴隨至少一次的MinorGC(但非絕對,在Parallel Scavenger 收集器的收集策略裏就有直接進行MajorGC的策略選擇過程)

MajorGC的速度通常會比MinorGC10倍以上。

對象的分配策略:

大多數狀況下,對象在新生代Eden區中分配。當Eden區沒有足夠空間進行分配時,虛擬機將發起一次GC

大對象直接進入老年代。所謂的大對象是指,須要大量連續內存空間的Java對象,最經典的大對象就是那種很長字符串以及數組。

長期存活的對象將進入老年代。虛擬機爲了區別對象是應該放在老年代仍是新生代,給每一個對象定義了一個對象年齡計數器。若是對象在Eden出生並通過第一次MinorGC後任然存活,而且能被Survivor容納的話,將被移動到Survivor空間,而且將年齡設置爲1.對象每在Survivor區中熬過一次MinorGC,年齡就會增長1歲。當他的年齡超過必定程度(默認是15),就會被晉升到老年代中。對象晉升到老年代的閾值能夠經過參數-XX:MaxTenuringThreshold設置。

動態對象年齡綁定:

爲了能更好地適應不一樣程序的內存情況,虛擬機並非永遠地要求對象的年齡必須達到了MaxTenuringThreshold才晉升老年代,若是在Survivor空間中相同年齡全部對象大小綜合大於Survivor空間的一半,年齡大於或者等於該年齡的對象就能夠直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。

空間分配擔保:

在發生MinorGC以前,虛擬機會先檢查老年代最大可用的連續空間是否大於新生代全部對象的總空間,若是這個條件成立,那麼MinorGC能夠確保是安全的。若是不成立,則虛擬機會查看HandlePromotionFailure設置值是否容許擔保失敗。若是容許,那麼會繼續檢查老年代最大可用的連續空間是否大於歷次晉升到老年代對象的平均大小,若是大於則嘗試進行一次MinorGC,儘管此次MinorGC是有風險的;若是小於,或者HandlePromotionFailure設置不容許冒險,那麼也要改成進行一次FullGC

風險其實就是指:老年代的空間不必定能容納青年代全部存活的對象,一旦不能容納,那就還須要進行一次Full GC

四,垃圾回收器

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

相關文章
相關標籤/搜索