日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

无招胜有招之Java进阶JVM(五)垃圾回收

發(fā)布時(shí)間:2024/2/28 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 无招胜有招之Java进阶JVM(五)垃圾回收 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

垃圾檢測、回收算法

垃圾收集器一般必須完成兩件事:檢測出垃圾;回收垃圾。怎么檢測出垃圾?一般有以下幾種方法:

引用計(jì)數(shù)法:給一個(gè)對象添加引用計(jì)數(shù)器,每當(dāng)有個(gè)地方引用它,計(jì)數(shù)器就加1;引用失效就減1。

好了,問題來了,如果我有兩個(gè)對象A和B,互相引用,除此之外,沒有其他任何對象引用它們,實(shí)際上這兩個(gè)對象已經(jīng)無法訪問,即是我們說的垃圾對象。但是互相引用,計(jì)數(shù)不為0,導(dǎo)致無法回收,所以還有另一種方法:

可達(dá)性分析算法:以根集對象為起始點(diǎn)進(jìn)行搜索,如果有對象不可達(dá)的話,即是垃圾對象。這里的根集一般包括java棧中引用的對象、方法區(qū)常良池中引用的對象

本地方法中引用的對象等。

總之,JVM在做垃圾回收的時(shí)候,會(huì)檢查堆中的所有對象是否會(huì)被這些根集對象引用,不能夠被引用的對象就會(huì)被垃圾收集器回收。一般回收算法也有如下幾種:

1.標(biāo)記-清除(Mark-sweep)

算法和名字一樣,分為兩個(gè)階段:標(biāo)記和清除。標(biāo)記所有需要回收的對象,然后統(tǒng)一回收。這是最基礎(chǔ)的算法,后續(xù)的收集算法都是基于這個(gè)算法擴(kuò)展的。

不足:效率低;標(biāo)記清除之后會(huì)產(chǎn)生大量碎片。效果圖如下:

2.復(fù)制(Copying)

此算法把內(nèi)存空間劃為兩個(gè)相等的區(qū)域,每次只使用其中一個(gè)區(qū)域。垃圾回收時(shí),遍歷當(dāng)前使用區(qū)域,把正在使用中的對象復(fù)制到另外一個(gè)區(qū)域中。此算法每次只處理正在使用中的對象,因此復(fù)制成本比較小,同時(shí)復(fù)制過去以后還能進(jìn)行相應(yīng)的內(nèi)存整理,不會(huì)出現(xiàn)“碎片”問題。當(dāng)然,此算法的缺點(diǎn)也是很明顯的,就是需要兩倍內(nèi)存空間。效果圖如下:

3.標(biāo)記-整理(Mark-Compact)

此算法結(jié)合了“標(biāo)記-清除”和“復(fù)制”兩個(gè)算法的優(yōu)點(diǎn)。也是分兩階段,第一階段從根節(jié)點(diǎn)開始標(biāo)記所有被引用對象,第二階段遍歷整個(gè)堆,把清除未標(biāo)記對象并且把存活對象“壓縮”到堆的其中一塊,按順序排放。此算法避免了“標(biāo)記-清除”的碎片問題,同時(shí)也避免了“復(fù)制”算法的空間問題。效果圖如下:

(1,2,3 圖文摘自?http://pengjiaheng.iteye.com/blog/520228,感謝原作者。)

4.分代收集算法

這是當(dāng)前商業(yè)虛擬機(jī)常用的垃圾收集算法。分代的垃圾回收策略,是基于這樣一個(gè)事實(shí):不同的對象的生命周期是不一樣的。因此,不同生命周期的對象可以采取不同的收集方式,以便提高回收效率。

為什么要運(yùn)用分代垃圾回收策略?在java程序運(yùn)行的過程中,會(huì)產(chǎn)生大量的對象,因每個(gè)對象所能承擔(dān)的職責(zé)不同所具有的功能不同所以也有著不一樣的生命周期,有的對象生命周期較長,比如Http請求中的Session對象,線程,Socket連接等;有的對象生命周期較短,比如String對象,由于其不變類的特性,有的在使用一次后即可回收。試想,在不進(jìn)行對象存活時(shí)間區(qū)分的情況下,每次垃圾回收都是對整個(gè)堆空間進(jìn)行回收,那么消耗的時(shí)間相對會(huì)很長,而且對于存活時(shí)間較長的對象進(jìn)行的掃描工作等都是徒勞。因此就需要引入分治的思想,所謂分治的思想就是因地制宜,將對象進(jìn)行代的劃分,把不同生命周期的對象放在不同的代上使用不同的垃圾回收方式。

如何劃分?將對象按其生命周期的不同劃分成:年輕代(Young Generation)、年老代(Old Generation)、持久代(Permanent Generation)。其中持久代主要存放的是類信息,所以與java對象的回收關(guān)系不大,與回收息息相關(guān)的是年輕代和年老代。這里有個(gè)比喻很形象

“假設(shè)你是一個(gè)普通的 Java 對象,你出生在 Eden 區(qū),在 Eden 區(qū)有許多和你差不多的小兄弟、小姐妹,可以把 Eden 區(qū)當(dāng)成幼兒園,在這個(gè)幼兒園里大家玩了很長時(shí)間。Eden 區(qū)不能無休止地放你們在里面,所以當(dāng)年紀(jì)稍大,你就要被送到學(xué)校去上學(xué),這里假設(shè)從小學(xué)到高中都稱為 Survivor 區(qū)。開始的時(shí)候你在 Survivor 區(qū)里面劃分出來的的“From”區(qū),讀到高年級了,就進(jìn)了 Survivor 區(qū)的“To”區(qū),中間由于學(xué)習(xí)成績不穩(wěn)定,還經(jīng)常來回折騰。直到你 18 歲的時(shí)候,高中畢業(yè)了,該去社會(huì)上闖闖了。于是你就去了年老代,年老代里面人也很多。在年老代里,你生活了 20 年 (每次 GC 加一歲),最后壽終正寢,被 GC 回收。有一點(diǎn)沒有提,你在年老代遇到了一個(gè)同學(xué),他的名字叫愛德華 (慕光之城里的帥哥吸血鬼),他以及他的家族永遠(yuǎn)不會(huì)死,那么他們就生活在永生代。”

?

具體區(qū)域可以通過VisualVM中的VisaulGC插件查看,如圖(openjdk 1.7):

年輕代:是所有新對象產(chǎn)生的地方。年輕代被分為3個(gè)部分——Enden區(qū)和兩個(gè)Survivor區(qū)(From和to)當(dāng)Eden區(qū)被對象填滿時(shí),就會(huì)執(zhí)行Minor GC。并把所有存活下來的對象轉(zhuǎn)移到其中一個(gè)survivor區(qū)(假設(shè)為from區(qū))。Minor GC同樣會(huì)檢查存活下來的對象,并把它們轉(zhuǎn)移到另一個(gè)survivor區(qū)(假設(shè)為to區(qū))。這樣在一段時(shí)間內(nèi),總會(huì)有一個(gè)空的survivor區(qū)。經(jīng)過多次GC周期后,仍然存活下來的對象會(huì)被轉(zhuǎn)移到年老代內(nèi)存空間。通常這是在年輕代有資格提升到年老代前通過設(shè)定年齡閾值來完成的。需要注意,Survivor的兩個(gè)區(qū)是對稱的,沒先后關(guān)系,from和to是相對的。

年老代:在年輕代中經(jīng)歷了N次回收后仍然沒有被清除的對象,就會(huì)被放到年老代中,可以說他們都是久經(jīng)沙場而不亡的一代,都是生命周期較長的對象。對于年老代和永久代,就不能再采用像年輕代中那樣搬移騰挪的回收算法,因?yàn)槟切τ谶@些回收戰(zhàn)場上的老兵來說是小兒科。通常會(huì)在老年代內(nèi)存被占滿時(shí)將會(huì)觸發(fā)Full GC,回收整個(gè)堆內(nèi)存。

持久代:用于存放靜態(tài)文件,比如java類、方法等。持久代對垃圾回收沒有顯著的影響。?

分代回收的效果圖如下:

我這里之所以最后講分代,是因?yàn)榉执锷婕傲饲懊鎺追N算法。年輕代:涉及了復(fù)制算法;年老代:涉及了“標(biāo)記-整理(Mark-Sweep)”的算法。

總結(jié)

以上是生活随笔為你收集整理的无招胜有招之Java进阶JVM(五)垃圾回收的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。