上面時候?qū)ο蟛沤凶鏊廊チ耍?br> 兩個最主要的方法:引用計數(shù)算法和根搜索法。 引用分為強(qiáng)引用,軟引用,弱引用,虛引用,這四種引用強(qiáng)度一次逐漸減弱。
實際操作中是怎么處理的呢?
首先使用根搜索法對堆中對象進(jìn)行第一次標(biāo)記,如果沒有與根對象相連,那么就把他們進(jìn)行標(biāo)記出來,并進(jìn)行一次篩選,帥選的條件是此對象是否有必要執(zhí)行finalize()方法。當(dāng)對象沒有覆蓋finalize方法,或者finalize()方法已經(jīng)被虛擬機(jī)調(diào)用過,虛擬機(jī)將這兩種情況都視為“沒有必要執(zhí)行”。
如果這個對象被判定為有必要執(zhí)行finalize方法,那么這個對象就會被放置在一個名為F-Queue隊列之中,并在稍后有一條虛擬機(jī)自動建立的,低優(yōu)先級的Finilize線程去執(zhí)行。這里所謂的執(zhí)行是指虛擬機(jī)會觸發(fā)這個方法,但并不承諾會等待它執(zhí)行結(jié)束。這樣做的原因是,如果一個對象在finalize方法中執(zhí)行緩慢,或者發(fā)生了死循環(huán),將很可能會導(dǎo)致F-Queue隊列中的其他對象永久處于等待狀態(tài),甚至導(dǎo)致整個內(nèi)存回收系統(tǒng)崩潰。finalize方法是對象逃脫死亡命運的最后一次機(jī)會,稍后GC將對F-Queue中的對象進(jìn)行第二次小規(guī)模的標(biāo)記,如果對象要在finalize中成功的拯救自己,只要重新與引用鏈上的任何一個對象建立關(guān)聯(lián)即可,譬如把自己賦值給某個變量或?qū)ο蟮某蓡T變量,那么第二次標(biāo)記時它將被移除出“即將回收”的集合;如果對象這時候還沒有逃脫,那它就真的離死不遠(yuǎn)了。
回收方法區(qū),類需要同時滿足3個條件才能算是無用的類:
1類所有的實例都已經(jīng)被回收;2加載該類的classloader已經(jīng)被回收;3該類對應(yīng)的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。
垃圾回收的三個方法:
1標(biāo)記清除算法
2復(fù)制算法
3標(biāo)記整理算法
垃圾收集器,對應(yīng)新生代和永久代使用不同的垃圾回收方法。
內(nèi)存分配與回收策略:
1對象優(yōu)先在Eden分配;
2大對象直接進(jìn)入老年代,大對象是指,需要大量連續(xù)內(nèi)存空間的java對象。最典型的就是很長的字符串及數(shù)組。
3長期存活的對象將進(jìn)入老年代。VM給每個對象一個Age計數(shù)器,經(jīng)過一次Minor GC仍活著就+1,達(dá)到某個閾值就進(jìn)去;
4動態(tài)對象年齡判定。為了能更好的適應(yīng)不同程序的內(nèi)存狀況,虛擬機(jī)并不總是要求對象的年齡必須達(dá)到MaxTenuringThreshold才能晉升老年代,如果在Survivor空間中相同年齡所有對象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對象就可以直接進(jìn)入老年代,無需等到MaxTenuringThreshold中要求的年齡。
5空間分配擔(dān)保。在發(fā)生Minor GC時,虛擬機(jī)會檢測之前每次晉升到老年代的平均大小是否大于老年大的剩余空間大小,如果大于,則改為直接進(jìn)行一次Full GC,如果小于,則查看HandlePromotionFailue設(shè)置是否允許擔(dān)保失敗;如果允許,那只會進(jìn)行Minor GC;如果不允許,則也要改為進(jìn)行一次Full GC。
最后大致講述一下整體流程
我們首先要明確,根據(jù)分代收集算法,我們的java堆被分為新生代和老年代(他們的特點不同,一個朝生夕死,一個相對穩(wěn)定)。新生代又被進(jìn)一步的細(xì)分,分為一個eden區(qū)和2個survivor區(qū)。一般情況下,我們制定他們的內(nèi)存大小比例為8:1:1。根據(jù)survivor這個英文單詞的含義,我們就大致可以猜出他們主要用來存放幸存者。
