GC: gc不僅負(fù)責(zé)垃圾回收,還決定內(nèi)存分配。 java內(nèi)存管理主要是對(duì)內(nèi)存中的對(duì)象進(jìn)行內(nèi)存的分配和回收,我們都知道當(dāng)我們創(chuàng)建一個(gè)對(duì)象時(shí),對(duì)象的引用放在棧(Stack)中,對(duì)象放在堆(heap)中,gc只回收堆里面的對(duì)象。當(dāng)gc檢測(cè)到一個(gè)堆中的一個(gè)對(duì)象不在被引用時(shí),就會(huì)對(duì)這個(gè)對(duì)象進(jìn)行回收。 當(dāng)我們創(chuàng)建一個(gè)對(duì)象時(shí),gc就會(huì)監(jiān)視這個(gè)對(duì)象的地址,大小以及狀態(tài)。gc有特定的回收算法,通常使用有向圖來(lái)記錄管理堆中的對(duì)象,通過(guò)這種方式來(lái)確定那些對(duì)象正在被引用,那些已經(jīng)不在被引用,當(dāng)一個(gè)對(duì)象不在被引用時(shí),gc就有權(quán)回收這個(gè)對(duì)象。當(dāng)然可以使用System.gc();Runtime.getRuntime().gc();來(lái)顯示調(diào)用gc。但是java規(guī)范不保證gc不一定立即回收。 gc可以使我們?cè)陂_(kāi)發(fā)時(shí)候不用考慮內(nèi)存回收的事情了,可以防止內(nèi)存泄漏。
垃圾收集的實(shí)現(xiàn)種類: 1. 引用計(jì)數(shù): 一個(gè)A對(duì)象,如果有程序使用了這個(gè)引用對(duì)象,那么引用計(jì)數(shù)加1,當(dāng)一個(gè)對(duì)象使用完畢之后引用計(jì)數(shù)減1,那么引用計(jì)數(shù)為0的時(shí)候,則可以回收。 他不能識(shí)別循環(huán)引用
2. 跟蹤收集: root set :當(dāng)前正在執(zhí)行的線程;全局或者靜態(tài)變量;JVM Handles;JNDI Handles 從root set 開(kāi)始掃描有引用的對(duì)象,如果某個(gè)對(duì)象不可以到達(dá),則說(shuō)明這個(gè)對(duì)象已經(jīng)dead,GC可以對(duì)其回收。也就是說(shuō):如果A對(duì)象引用了B對(duì)象,那么虛擬機(jī)會(huì)記住這個(gè)引用路徑,同時(shí)B對(duì)象引用了C對(duì)象,那么也會(huì)記錄這個(gè)路徑如果一個(gè)對(duì)象沒(méi)有在路徑圖中,那么可以收集。 需要維護(hù)一張引用的全景圖,增加了內(nèi)存開(kāi)銷,和圖的遍歷開(kāi)銷。
3. 基于對(duì)象跟蹤的分代增量收集 : 基于對(duì)象跟蹤:說(shuō)明是由跟蹤收集發(fā)展而來(lái)的,分代是指對(duì)堆進(jìn)行了合理的劃分, 增量收集:不是每一次全部收集,而是累積的增量收集。
Sun的JVM將整個(gè)堆分為三代:YoungGen(新生代),OldGen(年老代),和PermGen(持久區(qū)): Minor GC:通常是指對(duì)新生代的回收。 Major GC:通常是指對(duì)年老代的回收。 Full GC:Major GC除并發(fā)gc外均需對(duì)整個(gè)堆進(jìn)行掃描和回收。 復(fù)制拷貝算法:要拷貝大量數(shù)據(jù),不會(huì)產(chǎn)生碎片。 標(biāo)記算法:從引用根節(jié)點(diǎn)開(kāi)始標(biāo)記所有被引用的對(duì)象,把未被引用的對(duì)象清除。要遍歷所有對(duì)象,會(huì)產(chǎn)生碎片。 young 又分為eden,survivor1(from space ),survivor2(to sapce ).youngGen區(qū)里面的對(duì)象的生命周期比較短,gc對(duì)這些對(duì)象進(jìn)行回收的時(shí)候采用復(fù)制拷貝算法。 eden 每當(dāng)一個(gè)對(duì)象創(chuàng)建的時(shí)候分配的這個(gè)區(qū)域。當(dāng)eden無(wú)法分配時(shí),觸發(fā)一次Minor gc。gc每次回收的時(shí)候都將eden區(qū)存活的對(duì)象和survivor1中的對(duì)象拷貝到survivor2中,eden和survivor1清空;當(dāng)gc執(zhí)行下次回收的時(shí)候?qū)den和survivor2中的對(duì)象拷貝到surivor1中,清空eden和survivor2。依次這樣執(zhí)行;經(jīng)過(guò)數(shù)次回收將依然存活的對(duì)象復(fù)制到OldGen區(qū)。 OldGen 當(dāng)對(duì)象從年輕代晉升到老年代之前,會(huì)檢測(cè)老年區(qū)的剩余空間是否大于要晉升對(duì)象的大小,如果小于則直接進(jìn)行一次Full GC,以便讓老年去騰出更多的空間,然后再進(jìn)行Minor GC,把年輕代的對(duì)象復(fù)制到老年代;如果大于,則根據(jù)條件(HandlePromotionFailure設(shè)置)進(jìn)行Minor GC 和 Full GC。 老年區(qū)采用標(biāo)記算法,因?yàn)槔夏陞^(qū)對(duì)象的生命周期都是比較長(zhǎng)的,采用拷貝算法要拷貝大量的數(shù)據(jù)。采用標(biāo)記算法每次gc回收都要遍歷所有的對(duì)象。 PermGen 主要存放加載進(jìn)來(lái)的類信息,包括方法,屬性,常量池等,滿了之后可能會(huì)引起out of memory 錯(cuò)誤。
|
|