如何判斷對象可以被回收


jvm是如何判斷對象可以被回收的?

方法一:引用計數法

  jvm給對象中添加一個引用計數器,每當有一個地方引用它,計數器加1,當引用失效,計數器減1,任何時候計數器為0的對象就是不可能再被使用的。

  此方法存在的局限性:不能解決對象之間相互引用的問題。例如:

  

 

   

 

  如上圖所示,棧中引用了堆中對象objA和objB,此時objA和objB的引用計數器都加1;而且把objA賦值給objB的成員變量,objB賦值給objA的成員變量,也就是說objA和objB之間存在引用,此時objA和objB的引用計數器都再加1變成2。而當棧中對objA和objB的引用失效了之后,此時objA和objB實際上已經是無用對象了,但是objA和objB的引用計數器也都只是減1尚且不為0,因此objA和objB兩個對象都不會被回收。任然占用堆的內存。這樣的情況多了就可能出現內存泄漏問題。

方法二:可達性分析算法

  通過一系列的稱為“GC Roots”的對象作為起始點,從這些節點開始向下搜索,搜索所走過的路徑稱為引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引用鏈相連(用圖論的話來說,就是從GC Roots到這個對象不可達)時,則證明此對象是不可用的。

  

 

   

  在Java語言中,可作為GC Roots的對象包括下面幾種:

    虛擬機棧(棧幀中的本地變量表)中引用的對象。

    方法區中類靜態屬性引用的對象。

    方法區中常量引用的對象。

    本地方法棧中JNI(即一般說的Native方法)引用的對象

方法三:

  常見引用類型:

    強引用:普通的變量引用

    軟引用:將對象用SoftReference軟引用類型的對象包裹,正常情況不會被回收,但是GC做完后發現釋不出空間存放新的對象,則會把這些軟引用的對象回收掉。軟引用可用來實現對內存敏感度不高的高速緩存。public static SoftReference<User> user = new SoftReference<User>(new User());

    弱引用:將對象用WeakReference弱引用類型的對象包裹,弱引用跟沒有引用差不多,GC會直接回收掉,很少用。

    public static WeakReference<User> user = new WeakReference<User>(new User());

    虛引用:虛引用也成為幽靈引用或幻影引用,它是最弱的一種引用,幾乎不用。

方法四:finalize()方法最終判定對象是否存活

  即使在可達性分析算法中不可達的對象,也並非是“非死不可”de ,這時候它們暫時處於“緩刑”階段,要真正宣告一個對象死亡,至少要經歷再次標記過程。

  標記的前提是對象在進行可達性分析后發現沒有與GC Roots相連接的引用鏈。

  1、第一次標記並進行一次篩選:

    對象沒有覆蓋finalize()方法,對象將直接被回收。

  2、第二次標記:

    如果這個對象覆蓋了finalize()方法,只要重新與引用鏈上的任何一個對象建立關聯即可。

PS:如何判斷一個類是無用的類

  類需要同時滿足下面3個條件才能算是無用的類:

  1、該類所有的實例都已經被回收,也就是堆中不存在該類的任何實例。

  2、加載該類的ClassLoader已經被回收。

  3、該類對應的java.lang.Class對象沒有任何地方唄引用,無法在任何地方通過反射訪問該類的方法。


免責聲明!

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



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