- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- 淺談Java垃圾回收機制
java中,什么樣的對象是垃圾?有人說(shuō):沒(méi)有被引用的對象就是垃圾對象.我一開(kāi)始對此也是深信不疑的,但是當年我這么回答面試官的時(shí)候,得到的是一個(gè)大大的白眼.
判斷一個(gè)對象是否是垃圾,有兩種算法,一種是引用計數法,但是,這種方法解決不了循環(huán)引用的問(wèn)題.
/**循環(huán)問(wèn)題*/ public class Demo{ public Demo instance; public static void main(String[] args) { Demo a=new Demo(); Demo b=new Demo(); a.instance=b; b.instance=a; a=null; b=null; } }
另外一種方法,可以解決這種循環(huán)引用問(wèn)題,那就是可達算法.關(guān)于可達算法,就我目前所知道的,有兩種解釋:
大眾說(shuō)法:
通過(guò)一系列的稱(chēng)謂“GC Roots”的對象作為起始點(diǎn),從這些節點(diǎn)開(kāi)始向下搜索,搜索所有走過(guò)的路徑為引用鏈,當一個(gè)對象到GC Roots沒(méi)有任何引用鏈項鏈時(shí),則證明此對象時(shí)不可用的.
某位前輩的理解:
選取一個(gè)對象作為GC Roots,調用其它對象去指向這個(gè)GC Roots,如果這些對象最終到達GC Roots,那表明所選取的對象不是垃圾.反之,如果對象到不了GC Roots,那么所選取的對象就是垃圾對象,就可以進(jìn)行垃圾回收了.(這是一種說(shuō)法);
對象指向GC Roots所形成的鏈條叫GC鏈.
至于這兩種方法誰(shuí)對誰(shuí)錯,這就要看個(gè)人的水平了.
不管怎么樣,垃圾反正是產(chǎn)生了,那么接下來(lái)就是該怎么回收垃圾了.
在說(shuō)垃圾回收前,先說(shuō)一個(gè)題外話(huà),我上面所說(shuō)的垃圾對象,其實(shí)是指一般的對象,因為靜態(tài)對象有些不同.
我經(jīng)常聽(tīng)人說(shuō):靜態(tài)方法隨著(zhù)類(lèi)的加載而加載,隨著(zhù)類(lèi)的消失而消失.但是,現在在我看來(lái),這種說(shuō)法是有問(wèn)題的.
因為,靜態(tài)對象要成為垃圾被回收,要滿(mǎn)足三個(gè)條件:
1. 這個(gè)類(lèi)的對象變成了垃圾
2. 加載這個(gè)類(lèi)的類(lèi)加載器變成了垃圾
3. 關(guān)于這個(gè)對象的class對象也變成了垃圾
只有滿(mǎn)足這三個(gè)條件,靜態(tài)對象才會(huì )變成垃圾被回收,要不然靜態(tài)對象會(huì )一直存在于永久帶中.
既然要說(shuō)垃圾回收,那么我們就先來(lái)看看跟垃圾回收密切相關(guān)的堆內存(新生代和年老代)
如圖所示:
堆內存按1:2被劃分成了年輕代(新生代)和年老代.新生代又被按照8:1:1的比例分為一個(gè)eden區和兩個(gè)survivor(survivor0,survivor1)區
關(guān)于分區,我只講到這里,有興趣的可以自己研究.
如圖所示:標記清除算法分成兩步,第一步,標記要回收的垃圾對象,第二步就是清除被標記的垃圾對象.
同樣,如圖所示,標記清除算法會(huì )產(chǎn)生大量的內存碎片,而且效率低.所以,為了解決這個(gè)問(wèn)題,出現了復制清除算法.
如圖所示,所謂復制清除算法,就是在要進(jìn)行垃圾回收的時(shí)候,先將活著(zhù)的對象整齊的復制到一塊空閑區域,然后再將原來(lái)的區域的垃圾全部清除.
復制清除算法的優(yōu)點(diǎn):效率高于標記清除算法,活著(zhù)的對象是整齊排列的,沒(méi)有內存碎片.
但是這個(gè)方法的缺點(diǎn)也很明顯,那就是浪費空間.,畢竟如果按照1:1比例來(lái)劃分空間的話(huà),那么將會(huì )有50%的空間被浪費.不過(guò),在jvm中,年輕代空間并不是按照1:1來(lái)劃分的,而是按照8:1:1的比例分為一個(gè)eden區和兩個(gè)survivor(survivor0,survivor1)區。一個(gè)Eden區,兩個(gè) Survivor區(一般而言)。大部分對象在Eden區中生成?;厥諘r(shí)先將eden區存活對象復制到一個(gè)survivor0區,然后清空eden區,當這個(gè)survivor0區也存放滿(mǎn)了時(shí),則將eden區和survivor0區存活對象復制到另一個(gè)survivor1區,然后清空eden和這個(gè)survivor0區,此時(shí)survivor0區是空的,然后將survivor0區和survivor1區交換,即保持survivor1區為空,這樣的過(guò)程也被叫做Minor GC,每進(jìn)行Minor GC一次,存活著(zhù)的對象的年齡就會(huì )加1,當存活著(zhù)的對象的年齡到達15歲時(shí),就會(huì )被送進(jìn)年老代.
當然,當整個(gè)當survivor1區不足以存放 eden和survivor0的存活對象時(shí),也會(huì )將存活對象直接存放到年老代。若是年老代也滿(mǎn)了就會(huì )觸發(fā)一次Full GC,也就是新生代、老年代都進(jìn)行回收
將活著(zhù)的對象一個(gè)接一個(gè)的按順序排好,然后再清除變成垃圾的對象.這種方法不會(huì )造成碎片,也不會(huì )造成內存的浪費.但是效率不高.所以,這種方法不適合在年輕代使用,而是在對象生命力很頑強的年老代使用
所謂分類(lèi)算法,就是根據內存的不同,采用不同的垃圾回收方式(上面的1,2,3)進(jìn)行垃圾回收.
暫時(shí)就先說(shuō)到這里,因為再說(shuō)下去,還會(huì )有什么GC停頓以及垃圾收集器等.如果大家想要了解更多的垃圾回收的知識,可以看類(lèi)似<<深入理解Java虛擬機:JVM高級特性與最佳實(shí)踐>>等書(shū)籍.畢竟這些書(shū)是我的一位前輩推薦給我的.
到此這篇關(guān)于淺談Java垃圾回收機制的文章就介紹到這了,更多相關(guān)Java垃圾回收內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站