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