日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

垃圾收集策略與算法

程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧隨線程而生,也隨線程而滅;棧幀隨著方法的開始而入棧,隨著方法的結(jié)束而出棧。這幾個(gè)區(qū)域的內(nèi)存分配和回收都具有確定性,在這幾個(gè)區(qū)域內(nèi)不需要過(guò)多考慮回收的問(wèn)題,因?yàn)榉椒ńY(jié)束或者線程結(jié)束時(shí),內(nèi)存自然就跟隨著回收了。

而對(duì)于 JAVA 堆和方法區(qū),我們只有在程序運(yùn)行期間才能知道會(huì)創(chuàng)建哪些對(duì)象,這部分內(nèi)存的分配和回收都是動(dòng)態(tài)的,垃圾收集器所關(guān)注的正是這部分內(nèi)存。

判定對(duì)象是否存活

若一個(gè)對(duì)象不被任何對(duì)象或變量引用,那么它就是無(wú)效對(duì)象,需要被回收。

一 引用計(jì)數(shù)法(無(wú)法回收循環(huán)引用的對(duì)象)

在對(duì)象頭維護(hù)著一個(gè) counter 計(jì)數(shù)器,對(duì)象被引用一次則計(jì)數(shù)器 +1;若引用失效則計(jì)數(shù)器 -1。當(dāng)計(jì)數(shù)器為 0 時(shí),就認(rèn)為該對(duì)象無(wú)效了。

引用計(jì)數(shù)算法的實(shí)現(xiàn)簡(jiǎn)單,判定效率也很高,在大部分情況下它都是一個(gè)不錯(cuò)的算法。但是主流的 Java 虛擬機(jī)里沒有選用引用計(jì)數(shù)算法來(lái)管理內(nèi)存,主要是因?yàn)樗茈y解決對(duì)象之間循環(huán)引用的問(wèn)題。

例子:對(duì)象 objA 和 objB 都有字段 instance,令 objA.instance = objB 并且 objB.instance = objA,由于它們互相引用著對(duì)方,導(dǎo)致它們的引用計(jì)數(shù)都不為 0,于是引用計(jì)數(shù)算法無(wú)法通知 GC 收集器回收它們。

二 可達(dá)性分析法(更好)

所有和 GC Roots 直接或間接關(guān)聯(lián)的對(duì)象都是有效對(duì)象,和 GC Roots 沒有關(guān)聯(lián)的對(duì)象就是無(wú)效對(duì)象。

GC Roots 是指:

  1. Java 虛擬機(jī)棧(棧幀中的本地變量表)中引用的對(duì)象
  2. 本地方法棧中引用的對(duì)象
  3. 方法區(qū)中常量引用的對(duì)象
  4. 方法區(qū)中類靜態(tài)屬性引用的對(duì)象
  5. GC Roots 并不包括堆中對(duì)象所引用的對(duì)象,這樣就不會(huì)有循環(huán)引用的問(wèn)題。

引用的種類

判定對(duì)象是否存活與“引用”有關(guān)。在 JDK 1.2 以前,Java 中的引用定義很傳統(tǒng),一個(gè)對(duì)象只有被引用或者沒有被引用兩種狀態(tài),我們希望能描述這一類對(duì)象:當(dāng)內(nèi)存空間還足夠時(shí),則保留在內(nèi)存中;如果內(nèi)存空間在進(jìn)行垃圾手收集后還是非常緊張,則可以拋棄這些對(duì)象。很多系統(tǒng)的緩存功能都符合這樣的應(yīng)用場(chǎng)景。

Java技術(shù)干貨分享:JVM垃圾收集策略與算法

 

在 JDK 1.2 之后,Java 對(duì)引用的概念進(jìn)行了擴(kuò)充,將引用分為了以下四種。不同的引用類型,主要體現(xiàn)的是對(duì)象不同的可達(dá)性狀態(tài)reachable和垃圾收集的影響。

強(qiáng)引用(Strong Reference)

類似 "Object obj = new Object()" 這類的引用,就是強(qiáng)引用,只要強(qiáng)引用存在,垃圾收集器永遠(yuǎn)不會(huì)回收被引用的對(duì)象。但是,如果我們錯(cuò)誤地保持了強(qiáng)引用,比如:賦值給了 static 變量,那么對(duì)象在很長(zhǎng)一段時(shí)間內(nèi)不會(huì)被回收,會(huì)產(chǎn)生內(nèi)存泄漏。

軟引用(Soft Reference)

軟引用是一種相對(duì)強(qiáng)引用弱化一些的引用,可以讓對(duì)象豁免一些垃圾收集,只有當(dāng) JVM 認(rèn)為內(nèi)存不足時(shí),才會(huì)去試圖回收軟引用指向的對(duì)象。JVM 會(huì)確保在拋出 OutOfMemoryError 之前,清理軟引用指向的對(duì)象。軟引用通常用來(lái)實(shí)現(xiàn)內(nèi)存敏感的緩存,如果還有空閑內(nèi)存,就可以暫時(shí)保留緩存,當(dāng)內(nèi)存不足時(shí)清理掉,這樣就保證了使用緩存的同時(shí),不會(huì)耗盡內(nèi)存。

弱引用(Weak Reference)

弱引用的強(qiáng)度比軟引用更弱一些。當(dāng) JVM 進(jìn)行垃圾回收時(shí),無(wú)論內(nèi)存是否充足,都會(huì)回收只被弱引用關(guān)聯(lián)的對(duì)象。

虛引用(Phantom Reference)

虛引用也稱幽靈引用或者幻影引用,它是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用的存在,完全不會(huì)對(duì)其生存時(shí)間構(gòu)成影響。它僅僅是提供了一種確保對(duì)象被 finalize 以后,做某些事情的機(jī)制,比如,通常用來(lái)做所謂的 Post-Mortem 清理機(jī)制。

Java技術(shù)干貨分享:JVM垃圾收集策略與算法

 

回收堆中無(wú)效對(duì)象

對(duì)于可達(dá)性分析中不可達(dá)的對(duì)象,也并不是沒有存活的可能。

判定 finalize() 是否有必要執(zhí)行

JVM 會(huì)判斷此對(duì)象是否有必要執(zhí)行 finalize() 方法,如果對(duì)象沒有覆蓋 finalize() 方法,或者 finalize() 方法已經(jīng)被虛擬機(jī)調(diào)用過(guò),那么視為“沒有必要執(zhí)行”。那么對(duì)象基本上就真的被回收了。

如果對(duì)象被判定為有必要執(zhí)行 finalize() 方法,那么對(duì)象會(huì)被放入一個(gè) F-Queue 隊(duì)列中,虛擬機(jī)會(huì)以較低的優(yōu)先級(jí)執(zhí)行這些 finalize()方法,但不會(huì)確保所有的 finalize() 方法都會(huì)執(zhí)行結(jié)束。如果 finalize() 方法出現(xiàn)耗時(shí)操作,虛擬機(jī)就直接停止指向該方法,將對(duì)象清除。

對(duì)象重生或死亡

如果在執(zhí)行 finalize() 方法時(shí),將 this 賦給了某一個(gè)引用,那么該對(duì)象就重生了。如果沒有,那么就會(huì)被垃圾收集器清除。

任何一個(gè)對(duì)象的 finalize() 方法只會(huì)被系統(tǒng)自動(dòng)調(diào)用一次,如果對(duì)象面臨下一次回收,它的 finalize() 方法不會(huì)被再次執(zhí)行,想繼續(xù)在 finalize() 中自救就失效了。

回收方法區(qū)內(nèi)存

方法區(qū)中存放生命周期較長(zhǎng)的類信息、常量、靜態(tài)變量,每次垃圾收集只有少量的垃圾被清除。方法區(qū)中主要清除兩種垃圾:

  • 廢棄常量
  • 無(wú)用的類

判定廢棄常量

只要常量池中的常量不被任何變量或?qū)ο笠茫敲催@些常量就會(huì)被清除掉。比如,一個(gè)字符串 "bingo" 進(jìn)入了常量池,但是當(dāng)前系統(tǒng)沒有任何一個(gè) String 對(duì)象引用常量池中的 "bingo" 常量,也沒有其它地方引用這個(gè)字面量,必要的話,"bingo"常量會(huì)被清理出常量池。

判定無(wú)用的類

判定一個(gè)類是否是“無(wú)用的類”,條件較為苛刻。

  • 該類的所有對(duì)象都已經(jīng)被清除
  • 加載該類的 ClassLoader 已經(jīng)被回收
  • 該類的 java.lang.Class 對(duì)象沒有在任何地方被引用,無(wú)法在任何地方通過(guò)反射訪問(wèn)該類的方法。

一個(gè)類被虛擬機(jī)加載進(jìn)方法區(qū),那么在堆中就會(huì)有一個(gè)代表該類的對(duì)象:java.lang.Class。這個(gè)對(duì)象在類被加載進(jìn)方法區(qū)時(shí)創(chuàng)建,在方法區(qū)該類被刪除時(shí)清除。

Java技術(shù)干貨分享:JVM垃圾收集策略與算法

 

垃圾收集算法

學(xué)會(huì)了如何判定無(wú)效對(duì)象、無(wú)用類、廢棄常量之后,剩余工作就是回收這些垃圾。常見的垃圾收集算法有以下幾個(gè):

標(biāo)記-清除算法

標(biāo)記的過(guò)程是:遍歷所有的 GC Roots,然后將所有 GC Roots 可達(dá)的對(duì)象標(biāo)記為存活的對(duì)象。

清除的過(guò)程:將遍歷堆中所有的對(duì)象,將沒有標(biāo)記的對(duì)象全部清除掉。與此同時(shí),清除那些被標(biāo)記過(guò)的對(duì)象的標(biāo)記,以便下次的垃圾回收。

這種方法有兩個(gè)不足:

  • 效率問(wèn)題:標(biāo)記和清除兩個(gè)過(guò)程的效率都不高。
  • 空間問(wèn)題:標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,碎片太多可能導(dǎo)致以后需要分配較大對(duì)象時(shí),無(wú)法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。

復(fù)制算法(新生代)

為了解決效率問(wèn)題,“復(fù)制”收集算法出現(xiàn)了。它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊內(nèi)存用完,需要進(jìn)行垃圾收集時(shí),就將存活者的對(duì)象復(fù)制到另一塊上面,然后將第一塊內(nèi)存全部清除。這種算法有優(yōu)有劣:

  • 優(yōu)點(diǎn):不會(huì)有內(nèi)存碎片的問(wèn)題。
  • 缺點(diǎn):內(nèi)存縮小為原來(lái)的一半,浪費(fèi)空間。
  • 為了解決空間利用率問(wèn)題,可以將內(nèi)存分為三塊: Eden、From Survivor、To Survivor,比例是 8:1:1,每次使用 Eden 和其中一塊 Survivor。回收時(shí),將 Eden 和 Survivor 中還存活的對(duì)象一次性復(fù)制到另外一塊 Survivor 空間上,最后清理掉 Eden 和剛才使用的 Survivor 空間。這樣只有 10% 的內(nèi)存被浪費(fèi)。

但是我們無(wú)法保證每次回收都只有不多于 10% 的對(duì)象存活,當(dāng) Survivor 空間不夠,需要依賴其他內(nèi)存(指老年代)進(jìn)行分配擔(dān)保。

分配擔(dān)保

為對(duì)象分配內(nèi)存空間時(shí),如果 Eden+Survivor 中空閑區(qū)域無(wú)法裝下該對(duì)象,會(huì)觸發(fā) MinorGC 進(jìn)行垃圾收集。但如果 Minor GC 過(guò)后依然有超過(guò) 10% 的對(duì)象存活,這樣存活的對(duì)象直接通過(guò)分配擔(dān)保機(jī)制進(jìn)入老年代,然后再將新對(duì)象存入 Eden 區(qū)。

標(biāo)記-整理算法(老年代)

標(biāo)記:它的第一個(gè)階段與標(biāo)記/清除算法是一模一樣的,均是遍歷 GC Roots,然后將存活的對(duì)象標(biāo)記。

整理:移動(dòng)所有存活的對(duì)象,且按照內(nèi)存地址次序依次排列,然后將末端內(nèi)存地址以后的內(nèi)存全部回收。因此,第二階段才稱為整理階段。

這是一種老年代的垃圾收集算法。老年代的對(duì)象一般壽命比較長(zhǎng),因此每次垃圾回收會(huì)有大量對(duì)象存活,如果采用復(fù)制算法,每次需要復(fù)制大量存活的對(duì)象,效率很低。

分代收集算法

根據(jù)對(duì)象存活周期的不同,將內(nèi)存劃分為幾塊。一般是把 Java 堆分為新生代和老年代,針對(duì)各個(gè)年代的特點(diǎn)采用最適當(dāng)?shù)氖占惴ā?/p>

新生代:復(fù)制算法

老年代:標(biāo)記-清除算法、標(biāo)記-整理算法

分享到:
標(biāo)簽:收集 垃圾 JVM
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定