Java GC垃圾回收机制
Java提供了gc機(jī)制,jvm 中,程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧都是隨線程而生隨線程而滅,棧幀隨著方法的進(jìn)入和退出做入棧和出棧操作,實(shí)現(xiàn)了自動(dòng)的內(nèi)存清理,因此,我們的內(nèi)存垃圾回收主要集中于 java 堆和方法區(qū)中,在程序運(yùn)行期間,這部分內(nèi)存的分配和使用都是動(dòng)態(tài)的.垃圾回收機(jī)制,java不需要向C或者C++那樣需要程序員自行釋放內(nèi)存,由編程人員釋放資源,避免了資源釋放錯(cuò)誤和不必要的失誤而帶來的程序上的錯(cuò)誤,java提供的垃圾回收機(jī)制會(huì)在程序執(zhí)行的過程中自動(dòng)的判斷哪些資源不再被利用變成無用的資源,自動(dòng)調(diào)用垃圾回收機(jī)制回收無用的資源。
內(nèi)存分配上java用的HotSpot虛擬機(jī),會(huì)把堆區(qū)(存放對(duì)象)分為兩個(gè)區(qū)域:年輕代,年老代,兩個(gè)物理區(qū)域的對(duì)象可以互相轉(zhuǎn)移
年輕代(新生代):大部分對(duì)象都會(huì)存在這里,因?yàn)楹芏鄬?duì)象創(chuàng)建之后很快就會(huì)變得不可達(dá),在這里進(jìn)行的大都是比較小而且操作頻繁的回收,花費(fèi)的時(shí)間短 年老代(老年代):內(nèi)存相對(duì)較大,那些在年輕代被存活下來的對(duì)象也會(huì)被放到這里,對(duì)象會(huì)保留時(shí)間較長(zhǎng)的,都會(huì)分布在年老代,處在這里的對(duì)象大都是占用空間上升緩慢,并且回收頻率較低的對(duì)象,花費(fèi)的時(shí)間較長(zhǎng) 其中還有一塊叫做持久區(qū)的區(qū)域permanent generation,也叫方法區(qū),存放的是類的信息,可能在這里發(fā)生gc但是主要還是在年輕代和年老代發(fā)生gc 在年老代里存在類似于身份證的區(qū)域card table,存放的是所有年老代d對(duì)象指向年輕代的對(duì)象的引用,當(dāng)針對(duì)年輕代發(fā)生gc的時(shí)候,只需要來查詢這里來決定是否回收,不用再去遍歷整個(gè)年老代,這樣雖然帶來了內(nèi)存的開銷,但是節(jié)省了時(shí)間
詳細(xì)介紹年輕代:年輕代又被分為三個(gè)區(qū)域,
- ?一個(gè)伊甸園空間(Eden ),非常自在的一塊區(qū)域
- ?兩個(gè)幸存者空間(Survivor )
注意:剛剛創(chuàng)建的對(duì)象會(huì)保存在Eden里面的,對(duì)于那些長(zhǎng)期存在的對(duì)象會(huì)從幸存區(qū)轉(zhuǎn)移到年老代里 對(duì)于年老代的gc幾乎發(fā)生在年老代滿的時(shí)候,執(zhí)行的過程會(huì)根據(jù)回收的類型利用不同的方式,
垃圾收集算法:
“標(biāo)記-清除”(Mark-Sweep)算法,算法分為“標(biāo)記”和“清除”兩個(gè)階段:最開始標(biāo)記那些需要進(jìn)行回收的對(duì)象,在所有要回收的對(duì)象標(biāo)記之后,執(zhí)行清楚操作。回收無用的內(nèi)存。
它的主要缺點(diǎn)有兩個(gè):一個(gè)是效率問題,標(biāo)記和清除過程的效率都不高;另外一個(gè)是空間問題,標(biāo)記清除之后會(huì)產(chǎn)生大量不連續(xù)的內(nèi)存碎片,空間碎片太多可能會(huì)導(dǎo)致,當(dāng)程序在以后的運(yùn)行過程中需要分配較大對(duì)象時(shí)無法找到足夠的連續(xù)內(nèi)存而不得不提前觸發(fā)另一次垃圾收集動(dòng)作。
“復(fù)制”(Copying)算法,它將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用過的內(nèi)存空間一次清理掉。
這樣使得每次都是對(duì)其中的一塊進(jìn)行內(nèi)存回收,內(nèi)存分配時(shí)也就不用考慮內(nèi)存碎片等復(fù)雜情況,只要移動(dòng)堆頂指針,按順序分配內(nèi)存即可,實(shí)現(xiàn)簡(jiǎn)單,運(yùn)行高效。只是這種算法的代價(jià)是將內(nèi)存縮小為原來的一半,持續(xù)復(fù)制長(zhǎng)生存期的對(duì)象則導(dǎo)致效率降低。
”標(biāo)記-壓縮/整理“算法:復(fù)制收集算法在對(duì)象存活率較高時(shí)就要執(zhí)行較多的復(fù)制操作,效率將會(huì)變低。更關(guān)鍵的是,如果不想浪費(fèi)50%的空間,就需要有額外的空間進(jìn)行分配擔(dān)保,以應(yīng)對(duì)被使用的內(nèi)存中所有對(duì)象都100%存活的極端情況,所以在老年代一般不能直接選用這種算法。
根據(jù)老年代的特點(diǎn),有人提出了另外一種“標(biāo)記-整理”(Mark-Compact)算法,標(biāo)記過程仍然與“標(biāo)記-清除”算法一樣,但后續(xù)步驟不是直接對(duì)可回收對(duì)象進(jìn)行清理,而是讓所有存活的對(duì)象都向一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存
分代收集算法
新生代中,每次垃圾收集時(shí)都有大批對(duì)象死去,只有少量存活,就選用復(fù)制算法,只需要付出少量存活對(duì)象的復(fù)制成本就可以完成收集;
老年代中,其存活率較高、沒有額外空間對(duì)它進(jìn)行分配擔(dān)保,就應(yīng)該使用“標(biāo)記-整理”或“標(biāo)記-清理”算法進(jìn)行回收。
JDK7一共有5種GC類型:
Parallel Old GC (Parallel Compacting GC):算法和Parallel GC只在清理的步驟不一樣,會(huì)把對(duì)象放到一個(gè)預(yù)先處理好的區(qū)域 CMS GC:所用的時(shí)間最少,也是最先標(biāo)記,在標(biāo)記的時(shí)候,其他線程依然會(huì)運(yùn)行,節(jié)省時(shí)間,帶來的缺點(diǎn),就是相比于其他的gc會(huì)占用更多的內(nèi)存和cpu資源,因?yàn)樵跇?biāo)記的時(shí)候其他線程也在運(yùn)行,默認(rèn)情況下,這種回收算法回收的內(nèi)存空間不是壓縮的,不是連續(xù)的,前兩個(gè)都是連續(xù)的,會(huì)導(dǎo)致內(nèi)存碎片,只是節(jié)省了時(shí)間
G1 GC:一種最快的回收算法,他沒有年輕代和老年代的概念,每次創(chuàng)建的對(duì)象會(huì)放在一個(gè)區(qū)域的不同的格子上,直到滿了會(huì)執(zhí)行一次gc,但是目前不穩(wěn)定。
一般情況下調(diào)優(yōu)不會(huì)介紹
JVM 調(diào)優(yōu)主要在3點(diǎn): 1. 選擇合適的 GC collector. 2. 指定合適的 heap area大小. 3. 指定young generation的比例(或大小),它影響到 Full GC發(fā)生的頻率以及應(yīng)用暫停時(shí)間.
參考:
周志明. 深入理解Java虛擬機(jī)[M]. 北京:機(jī)械工業(yè)出版社, 2013: 61-100.
轉(zhuǎn)載于:https://www.cnblogs.com/duzhentong/p/7816593.html
總結(jié)
以上是生活随笔為你收集整理的Java GC垃圾回收机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Wintel物联网平台-Windows
- 下一篇: jQuery框架+DWR框架实现的Jav