JVM基礎(chǔ):GC策略&內(nèi)存申請、對象衰老
JVM里的GC(Garbage Collection)的算法有很多種,如標(biāo)記清除收集器,壓縮收集器,分代收集器等等,詳見HotSpot VM GC 的種類
現(xiàn)在比較常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即將內(nèi)存分為幾個區(qū)域,將不同生命周期的對象放在不同區(qū)域里:young generation,tenured generation和permanet generation。絕大部分的objec被分配在young generation(生命周期短),并且大部分的object在這里die。當(dāng)young generation滿了之后,將引發(fā)minor collection(YGC)。在minor collection后存活的object會被移動到tenured generation(生命周期比較長)。最后,tenured generation滿之后觸發(fā)major collection。major collection(Full gc)會觸發(fā)整個heap的回收,包括回收young generation。permanet generation區(qū)域比較穩(wěn)定,主要存放classloader信息。
young generation有eden、2個survivor 區(qū)域組成。其中一個survivor區(qū)域一直是空的,是eden區(qū)域和另一個survivor區(qū)域在下一次copy collection后活著的objecy的目的地。object在survivo區(qū)域被復(fù)制直到轉(zhuǎn)移到tenured區(qū)。
我們要盡量減少 Full gc 的次數(shù)(tenured generation 一般比較大,收集的時間較長,頻繁的Full gc會導(dǎo)致應(yīng)用的性能收到嚴(yán)重的影響)。
堆內(nèi)存GC
JVM(采用分代回收的策略),用較高的頻率對年輕的對象(young generation)進(jìn)行YGC,而對老對象(tenured generation)較少(tenured generation 滿了后才進(jìn)行)進(jìn)行Full GC。這樣就不需要每次GC都將內(nèi)存中所有對象都檢查一遍。
非堆內(nèi)存不GC
GC不會在主程序運(yùn)行期對PermGen Space進(jìn)行清理,所以如果你的應(yīng)用中有很多CLASS(特別是動態(tài)生成類,當(dāng)然permgen space存放的內(nèi)容不僅限于類)的話,就很可能出現(xiàn)PermGen Space錯誤。
內(nèi)存申請、對象衰老過程
一、內(nèi)存申請過程
•JVM會試圖為相關(guān)Java對象在Eden中初始化一塊內(nèi)存區(qū)域;
•當(dāng)Eden空間足夠時,內(nèi)存申請結(jié)束。否則到下一步;
•JVM試圖釋放在Eden中所有不活躍的對象(minor collection),釋放后若Eden空間仍然不足以放入新對象,則試圖將部分Eden中活躍對象放入Survivor區(qū);
•Survivor區(qū)被用來作為Eden及old的中間交換區(qū)域,當(dāng)OLD區(qū)空間足夠時,Survivor區(qū)的對象會被移到Old區(qū),否則會被保留在Survivor區(qū);
•當(dāng)old區(qū)空間不夠時,JVM會在old區(qū)進(jìn)行major collection;
•完全垃圾收集后,若Survivor及old區(qū)仍然無法存放從Eden復(fù)制過來的部分對象,導(dǎo)致JVM無法在Eden區(qū)為新對象創(chuàng)建內(nèi)存區(qū)域,則出現(xiàn)"Out of memory錯誤";
二、對象衰老過程
•新創(chuàng)建的對象的內(nèi)存都分配自eden。Minor collection的過程就是將eden和在用survivor space中的活對象copy到空閑survivor space中。對象在young generation里經(jīng)歷了一定次數(shù)(可以通過參數(shù)配置)的minor collection后,就會被移到old generation中,稱為tenuring。
•GC觸發(fā)條件
GC類型 | 觸發(fā)條件 | 觸發(fā)時發(fā)生了什么 | 注意 | 查看方式 |
YGC | eden空間不足 |
清空Eden+from survivor中所有no ref的對象占用的內(nèi)存 重新調(diào)整Eden 和from的大小(parallel GC會觸發(fā)此項(xiàng)) |
全過程暫停應(yīng)用 是否為多線程處理由具體的GC決定 |
jstat –gcutil gc log |
FGC |
old空間不足 |
清空heap中no ref的對象 permgen中已經(jīng)被卸載的classloader中加載的class信息 如配置了CollectGenOFirst,則先觸發(fā)YGC(針對serial GC) 如配置了ScavengeBeforeFullGC,則先觸發(fā)YGC(針對serial GC) |
全過程暫停應(yīng)用 是否為多線程處理由具體的GC決定 是否壓縮需要看配置的具體GC |
jstat –gcutil gc log |
permanent generation空間不足會引發(fā)Full GC,仍然不夠會引發(fā)PermGen Space錯誤。
參考:
http://jiangyongyuan.javaeye.com/blog/356502
http://www.helloying.com/blog/archives/164
相關(guān)內(nèi)容推薦:
原文鏈接:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037056.html
【系列文章】