垃圾判斷:
-
引用計(jì)數(shù)算法:
? ? ? ? 在對象中添加一個(gè)引用計(jì)數(shù)器,當(dāng)每有一個(gè)地方引用它時(shí),計(jì)數(shù)器值加一。當(dāng)引用失效時(shí),計(jì)數(shù)器值就減一。當(dāng)一個(gè)對象的計(jì)數(shù)器為零時(shí),表示該對象沒有被任何其他對象引用,因此可以被釋放。
- 優(yōu)點(diǎn):是可以及時(shí)回收垃圾對象,避免內(nèi)存泄漏,且不會產(chǎn)生暫停時(shí)間。
- 缺點(diǎn):維護(hù)計(jì)數(shù)器會增加額外的開銷。無法處理循環(huán)引用的情況,即兩個(gè)或多個(gè)對象互相引用,導(dǎo)致它們的計(jì)數(shù)器永遠(yuǎn)不為零,無法被回收。主流的Java虛擬機(jī)里面都沒有選用引用計(jì)數(shù)算法來管理內(nèi)存。
-
可達(dá)性分析算法:
????????通過 一系列稱為“GC Roots”的根對象作為起始節(jié)點(diǎn)集,從這些節(jié)點(diǎn)開始,根據(jù)引用關(guān)系向下搜索,搜索過程所走過的路徑稱為“引用鏈”,如果某個(gè)對象到GC Roots間沒有任何引用鏈相連, 或者用圖論的話來說就是從GC Roots到這個(gè)對象不可達(dá)時(shí),則證明此對象是不可能再被使用的。
GC Roots:虛擬機(jī)棧中引用的對象、在方法區(qū)中類靜態(tài)屬性引用的對象、在方法區(qū)中常量引用的對象、在本地方法棧中JNI引用的對象、所有被同步鎖持有的對象。
圖中雖然object4、object5、object6之間有互相引用,但它們到GC Roots不可達(dá),所以它們被判定為可回收對象。
再介紹一下引用的區(qū)別:
- 強(qiáng)引用:最常見的引用類型,就是new出來的對象。只要有強(qiáng)引用指向?qū)ο螅瑢ο缶筒粫焕厥掌骰厥铡?/li>
- 軟引用:只被軟引用關(guān)聯(lián)著的對象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常前,會把這些對象列進(jìn)回收范圍之中進(jìn)行第二次回收,如果這次回收還沒有足夠的內(nèi)存, 才會拋出內(nèi)存溢出異常。
- 弱引用:被弱引用關(guān)聯(lián)的對象只 能生存到下一次垃圾收集發(fā)生為止。當(dāng)垃圾收集器開始工作,無論當(dāng)前內(nèi)存是否足夠,都會回收掉只 被弱引用關(guān)聯(lián)的對象。
- 虛引用:一個(gè)對象是否有虛引用的 存在,完全不會對其生存時(shí)間構(gòu)成影響,也無法通過虛引用來取得一個(gè)對象實(shí)例。為一個(gè)對象設(shè)置虛引用關(guān)聯(lián)的唯一目的只是為了能在這個(gè)對象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知。
垃圾回收算法:
再將回收算法前我們需要了解兩個(gè)假說:
- 弱分代假說:絕大多數(shù)對象都是朝生夕滅的。
- 強(qiáng)分代假說:熬過越多次垃圾收集過程的對象就越難以消亡。
這兩個(gè)分代假說共同奠定了多款常用的垃圾收集器的一致的設(shè)計(jì)原則:收集器應(yīng)該將Java堆劃分 出不同的區(qū)域,然后將回收對象依據(jù)其年齡(年齡即對象熬過垃圾收集過程的次數(shù))分配到不同的區(qū)域之中存儲。
1、標(biāo)記清除算法
? ? ? ? 這個(gè)算法正如他的名字一樣,算法分為“標(biāo)記”和清除兩個(gè)階段。先把需要清除的對象進(jìn)行標(biāo)記,再標(biāo)記完成后,統(tǒng)一回收掉所有被標(biāo)記的對象,也可反過來,標(biāo)記存活的對象,統(tǒng)一回收所有未被標(biāo)記的對象。這是最基礎(chǔ)的收集算法,后續(xù)大多數(shù)的收集算法都是以標(biāo)記清除算法為基礎(chǔ)。
缺點(diǎn):第一個(gè)執(zhí)行效率不穩(wěn)定,如果有大量的對象需要清除,那么要進(jìn)行大量的標(biāo)記和清除,效率隨回收對象的增長而降低(所以比較適合老年代)。第二個(gè)內(nèi)存空間會存在碎片化問題,使其原本有足夠大空間,但由于太過碎片化無法存大對象,從而不得不提前觸發(fā)垃圾收集。
2、標(biāo)記復(fù)制算法
? ? ? ? 這個(gè)算法主要是用來解決當(dāng)有大量需要回收的對象時(shí)效率低下的問題。標(biāo)記的不要回收的對象,但我們要操作的是不需要回收的對象,此時(shí)我們所需要的時(shí)間就會少很多。這個(gè)方法則是半?yún)^(qū)復(fù)制法。我們將內(nèi)存等半分,每次只使用一塊,當(dāng)?shù)谝豢靸?nèi)存用完之后,只要將還存活的對象復(fù)制到第二塊去,然后將第一塊內(nèi)存清空。這樣往復(fù)操作。這個(gè)操作簡單高效,還解決了內(nèi)存碎片化問題。缺點(diǎn)就是每次內(nèi)存只能使用一半,太過于浪費(fèi)。
現(xiàn)在好多JVM大多使用這樣是收集算法去回收新生代,但是并不是1:1的比例,而是將其劃分為? Eden(8):Survivor(1):Survivor(1),每次分配內(nèi)存只使用Eden和其中一塊Survuvor,當(dāng)發(fā)生垃圾收集時(shí),將這個(gè)塊Survuvor和Eden中存活的對象復(fù)制到空閑那塊Survuvor上去,然后之間清空這個(gè)塊Survuvor和Eden。這個(gè)比例是通過測試得來的合理分配。這樣一來才浪費(fèi)了10%的內(nèi)存。可以接受。當(dāng)然如果出現(xiàn)了某次意外,一個(gè)Survivor無法存放所有的存活對象,可以向老年代“借”內(nèi)存用來存放。
3、標(biāo)記整理算法
標(biāo)記整理算法就是將需要回收的對象標(biāo)記然后清除,最后將存活下來的對象進(jìn)行整理。這樣子即利用了100%的內(nèi)存空間,又解決內(nèi)存碎片化問題。但是如果是向老年區(qū)這個(gè)每次清除都有大量的對象存活的區(qū)域,那么移動對象也是很大的負(fù)擔(dān)。所以一般都是先進(jìn)行標(biāo)記清除算法,待碎片化太過于嚴(yán)重再使用一次標(biāo)記整理算法,解決碎片化。這樣的方式被CMS收集器使用著。
ps:移動過程中要停止用戶線程。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-804913.html
?文章來源:http://www.zghlxwxcb.cn/news/detail-804913.html
?
到了這里,關(guān)于JVM:垃圾回收機(jī)制(GC)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!