簡單聊聊java中如何判定一個對象可回收


  背景

  說到java的特性,其中一個最重要的特性便是java通過new在堆中分配給對象的內存,不需要程序員主動去釋放,而是由java虛擬機自動的回收。這也是java和C++的主要區別之一;那么虛擬機是如何實現自動回收的呢?它的基本回收算法又是什么呢?  這篇隨筆先不介紹這些~ ~,熟話說 飯要一口一口地吃,路要一步一步地走嘛,這篇隨筆主要講解的是回收的前提:如何判斷一個對象可以回收。

  

  對java中如何判斷一個對象可以回收的一般性認識

  在沒有學習《深入理解java虛擬機》之前,對於java中判斷一個對象是否可以回收的方法,我自然而然的就想到了通過引用計數的方法就可以做到,我想的是:對象自身有一個引用計數器,每當有一個地方引用它時,計數器值就加1;當引用失效時(例如程序離開了引用對象它所在的作用域),計數器值減1;任何時刻計數器為零的對象就是不會再被使用的,內存自動回收時就可以對它進行回收了;

  這種方式又簡單,又高效,那為什么主流的java虛擬機沒有采用這種方式呢,其中主要的原因是這種方式很難解決對象之間相互循環引用的問題;看下面的簡單代碼例子:

public class Main {

public Object instance = null;

private static final int _1MB = 1024 * 1024;

//讓對象占用一定的內存空間,觸發回收
private byte[] bigSize = new byte[2 * _1MB];

public static void testGC(){

Main objA = new Main();

Main objB = new Main();
//objA中的instance對象引用objB,objB中的instance對象引用objA
objA.instance = objB;
objB.instance = objA;

//將兩個對象都設為null
objA = null;
objB = null;

System.gc();
}
}
對於上面的情況,如果java虛擬機采用引用計數的方式進行判斷對象是否可以回收,那么objA,和 objB是永遠也得不到回收的!

回到題目,那么java虛擬機采用什么方法來進行判斷一個對象是否可以被回收呢?
可達性分析算法:
  
正如算法名稱說描述的,這個算法的基本思想是:通過一系列稱為“GC Root” 的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈,當一個對象到GC Root 沒有任何引用鏈相連接(用圖論來說就是從根節點到這個對象節點不可達)時,則證明這個對象是不可用的;如圖1-1 所示,對象 5, 6, 7雖然互相有關聯,但是它們到GC Root 是不可達的,所以它們將被判定為可回收對象,即這幾個對象可以被判定已死亡;





                         
如圖 1-1:可達性分析算法判定對象是否可回收

  
看了上圖以后,又會有一個問題,就是如何選取GC Roots:
    包括以下下幾種對象:
    1.虛擬機棧中引用的對象(就是java函數體中的本地變量表)。
    2.方法區中類靜態屬性引用的對象。
    3.方法區中常量引用的對象。
    4.本地方法棧中JNI(即一般說的Native方法)引用的對象。
  

  以上就是我對java內存自動回收部分知識點的一個總結和分享,其中還有很多知識點需要去學習,比如方法區的存儲結構是怎樣的,存儲哪些類型數據信息,虛擬機如何管理這一塊內存區域等。
希望這次分享能對大家有所啟發,有所收獲~






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM