溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JVM的垃圾回收算法詳細介紹

發(fā)布時間:2021-09-14 16:00:44 來源:億速云 閱讀:178 作者:chen 欄目:大數(shù)據

這篇文章主要講解了“JVM的垃圾回收算法詳細介紹”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“JVM的垃圾回收算法詳細介紹”吧!

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

1,引用計數(shù)算法

一個對象如果沒有任何引用指向它,就可認為該對象已經”消亡“,這種方法有個缺點就是無法檢測到引用環(huán)的存在。

算法特點

1. 需要單獨的字段存儲計數(shù)器,增加了存儲空間的開銷;

2. 每次賦值都需要更新計數(shù)器,增加了時間開銷;

3. 垃圾對象便于辨識,只要計數(shù)器為0,就可作為垃圾回收;

4. 及時回收垃圾,沒有延遲性;

5. 不能解決循環(huán)引用的問題;

2,根搜索算法

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

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

Java虛擬機將以下對象定義為 GC Roots :

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

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

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

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

二,常用的垃圾回收算法

1,標記-清除算法。

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

首先是標記處所有需要回收的垃圾對象,標記完成之后統(tǒng)一進行回收處理。

該算法主要不足:

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

B),一個是空間的問題。標記清楚之后會導致大量不連續(xù)的內存碎片。空間碎片過多會導致在程序運行過程中需要分片大量內存的時候無法找到滿足連續(xù)內存而不得不提前出發(fā)另一次垃圾回收動作。標記-清除算法的執(zhí)行過程如下圖:

JVM的垃圾回收算法詳細介紹

2,復制算法

此算法把內存劃分為相等大小的兩個區(qū)域,每一只使用其中一個,回收過程中將存活的對象全部復制到另一個區(qū)域中,清空原區(qū)域。在年輕代中eden區(qū)和兩個survivor區(qū)就是使用了此種算法。這種算法只復制存活的對象,成本較低,而且不會出現(xiàn)內存碎片問題,缺點是需要2倍的內存空間。

JVM的垃圾回收算法詳細介紹

3,標記整理算法

復制收集算法在對象存活率較高的時候就要進行較多的復制操作,效率將會變的很低。更關鍵是,如果你不想浪費一半內存空間,就需要有額外的內存空間進行分配擔保,以應對被使用的內存中所有對象都100%存活的極端情況,所以老年代不采用這種算法。

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

JVM的垃圾回收算法詳細介紹

4,分代回收算法

當前商業(yè)虛擬機的垃圾回收器都采用分代收集算法,這種算法并沒有什么新的思想,只是根據對象存活周期的不同將內存花費為幾塊。一般是把java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當?shù)氖占惴?。在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去,只有少量存活,那就選用復制算法,只需要付出少量存活對象的復制陳本就可以完成收集。而老年代中因為對象存活率高,沒有額外空間對它進行分配擔保,就必須使用標記清除或者標記整理算法來進行垃圾回收。

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

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

新生代:所有新創(chuàng)建的對象都首先在新生代進行內存分配。新生代具體又分為3個區(qū),一個Eden區(qū)、一個From Survivor區(qū)和一個To Sruvivor區(qū)。大部分對象都被分配在Eden區(qū),當Eden區(qū)滿時,還存活的對象將被復制到From Survivor區(qū),當From Survivor區(qū)滿時,此區(qū)還存活的對象將被復制到To Survivor區(qū)。最后,當To Survivor區(qū)也滿時,這時從From Survivor區(qū)復制過來并且還存活的對象將被復制到老年代。

老年代:在年輕代中經歷了N次(一般是15次)GC后依然存活的對象,就會被放到老年代當中。因此,可以認為老年代是存放一些生命周期較長的對象。

持久代:用于存放靜態(tài)文件,如Java類等。

JVM的垃圾回收算法詳細介紹

GC的種類:

新生代GC(Minor GC):

指的是發(fā)生在新生代的垃圾收集動作,因為Java對象大多都具備朝生夕滅的特性,所以MinorGC非常頻繁,一般回收速度也比較快。

老年代GC(MajorGC/FullGC):

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

MajorGC的速度一般會比MinorGC慢10倍以上。

對象的分配策略:

大多數(shù)情況下,對象在新生代Eden區(qū)中分配。當Eden區(qū)沒有足夠空間進行分配時,虛擬機將發(fā)起一次GC。

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

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

動態(tài)對象年齡綁定:

為了能更好地適應不同程序的內存狀況,虛擬機并不是永遠地要求對象的年齡必須達到了MaxTenuringThreshold才晉升老年代,如果在Survivor空間中相同年齡所有對象大小綜合大于Survivor空間的一半,年齡大于或者等于該年齡的對象就可以直接進入老年代,無須等到MaxTenuringThreshold中要求的年齡。

空間分配擔保:

在發(fā)生MinorGC之前,虛擬機會先檢查老年代最大可用的連續(xù)空間是否大于新生代所有對象的總空間,如果這個條件成立,那么MinorGC可以確保是安全的。如果不成立,則虛擬機會查看HandlePromotionFailure設置值是否允許擔保失敗。如果允許,那么會繼續(xù)檢查老年代最大可用的連續(xù)空間是否大于歷次晉升到老年代對象的平均大小,如果大于則嘗試進行一次MinorGC,盡管這次MinorGC是有風險的;如果小于,或者HandlePromotionFailure設置不允許冒險,那么也要改為進行一次FullGC。

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

四,垃圾回收器

JVM的垃圾回收算法詳細介紹

感謝各位的閱讀,以上就是“JVM的垃圾回收算法詳細介紹”的內容了,經過本文的學習后,相信大家對JVM的垃圾回收算法詳細介紹這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI