淺談Java垃圾回收機制
一.什么是垃圾
java中,什么樣的對象是垃圾?有人說:沒有被引用的對象就是垃圾對象.我一開始對此也是深信不疑的,但是當年我這么回答面試官的時候,得到的是一個大大的白眼.
判斷一個對象是否是垃圾,有兩種算法,一種是引用計數法,但是,這種方法解決不了循環(huán)引用的問題.
/**循環(huá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)引用問題,那就是可達算法.關于可達算法,就我目前所知道的,有兩種解釋:
大眾說法:
通過一系列的稱謂“GC Roots”的對象作為起始點,從這些節(jié)點開始向下搜索,搜索所有走過的路徑為引用鏈,當一個對象到GC Roots沒有任何引用鏈項鏈時,則證明此對象時不可用的.
某位前輩的理解:
選取一個對象作為GC Roots,調用其它對象去指向這個GC Roots,如果這些對象最終到達GC Roots,那表明所選取的對象不是垃圾.反之,如果對象到不了GC Roots,那么所選取的對象就是垃圾對象,就可以進行垃圾回收了.(這是一種說法);
對象指向GC Roots所形成的鏈條叫GC鏈.
至于這兩種方法誰對誰錯,這就要看個人的水平了.
不管怎么樣,垃圾反正是產生了,那么接下來就是該怎么回收垃圾了.
二.怎么回收垃圾
2.1 靜態(tài)對象什么時候變成垃圾被回收
在說垃圾回收前,先說一個題外話,我上面所說的垃圾對象,其實是指一般的對象,因為靜態(tài)對象有些不同.
我經常聽人說:靜態(tài)方法隨著類的加載而加載,隨著類的消失而消失.但是,現在在我看來,這種說法是有問題的.
因為,靜態(tài)對象要成為垃圾被回收,要滿足三個條件:
1. 這個類的對象變成了垃圾
2. 加載這個類的類加載器變成了垃圾
3. 關于這個對象的class對象也變成了垃圾
只有滿足這三個條件,靜態(tài)對象才會變成垃圾被回收,要不然靜態(tài)對象會一直存在于永久帶中.
2.2 新生代和年老代
既然要說垃圾回收,那么我們就先來看看跟垃圾回收密切相關的堆內存(新生代和年老代)
如圖所示:
堆內存按1:2被劃分成了年輕代(新生代)和年老代.新生代又被按照8:1:1的比例分為一個eden區(qū)和兩個survivor(survivor0,survivor1)區(qū)
關于分區(qū),我只講到這里,有興趣的可以自己研究.
三、垃圾回收算法
3.1 標記清除算法
如圖所示:標記清除算法分成兩步,第一步,標記要回收的垃圾對象,第二步就是清除被標記的垃圾對象.
同樣,如圖所示,標記清除算法會產生大量的內存碎片,而且效率低.所以,為了解決這個問題,出現了復制清除算法.
3.2 復制清除算法(專門用于處理年輕代垃圾的)
如圖所示,所謂復制清除算法,就是在要進行垃圾回收的時候,先將活著的對象整齊的復制到一塊空閑區(qū)域,然后再將原來的區(qū)域的垃圾全部清除.
復制清除算法的優(yōu)點:效率高于標記清除算法,活著的對象是整齊排列的,沒有內存碎片.
但是這個方法的缺點也很明顯,那就是浪費空間.,畢竟如果按照1:1比例來劃分空間的話,那么將會有50%的空間被浪費.不過,在jvm中,年輕代空間并不是按照1:1來劃分的,而是按照8:1:1的比例分為一個eden區(qū)和兩個survivor(survivor0,survivor1)區(qū)。一個Eden區(qū),兩個 Survivor區(qū)(一般而言)。大部分對象在Eden區(qū)中生成。回收時先將eden區(qū)存活對象復制到一個survivor0區(qū),然后清空eden區(qū),當這個survivor0區(qū)也存放滿了時,則將eden區(qū)和survivor0區(qū)存活對象復制到另一個survivor1區(qū),然后清空eden和這個survivor0區(qū),此時survivor0區(qū)是空的,然后將survivor0區(qū)和survivor1區(qū)交換,即保持survivor1區(qū)為空,這樣的過程也被叫做Minor GC,每進行Minor GC一次,存活著的對象的年齡就會加1,當存活著的對象的年齡到達15歲時,就會被送進年老代.
當然,當整個當survivor1區(qū)不足以存放 eden和survivor0的存活對象時,也會將存活對象直接存放到年老代。若是年老代也滿了就會觸發(fā)一次Full GC,也就是新生代、老年代都進行回收
3.3 標記清理算法(年老代)
將活著的對象一個接一個的按順序排好,然后再清除變成垃圾的對象.這種方法不會造成碎片,也不會造成內存的浪費.但是效率不高.所以,這種方法不適合在年輕代使用,而是在對象生命力很頑強的年老代使用
3.4 分類算法
所謂分類算法,就是根據內存的不同,采用不同的垃圾回收方式(上面的1,2,3)進行垃圾回收.
暫時就先說到這里,因為再說下去,還會有什么GC停頓以及垃圾收集器等.如果大家想要了解更多的垃圾回收的知識,可以看類似<<深入理解Java虛擬機:JVM高級特性與最佳實踐>>等書籍.畢竟這些書是我的一位前輩推薦給我的.

到此這篇關于淺談Java垃圾回收機制的文章就介紹到這了,更多相關Java垃圾回收內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
idea 無法創(chuàng)建Scala class 選項的原因分析及解決辦法匯總
這篇文章主要介紹了idea 無法創(chuàng)建Scala class 選項的解決辦法匯總,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09

