JVM 怎麼判斷對象已經死了?

做者:勿念先生
https://blog.csdn.net/moHedon...

GC的歷史比Java還有久遠,咱們在思考GC時候須要思考三個問題:java

哪些內存須要回收?面試

何時回收?算法

如何回收?後端

在Java中程序計數器、虛擬機棧、本地方法棧這三個區域隨線程而生,隨線程而滅:棧中的棧幀隨着方法的調用和退出而有條不紊的進行着入棧和出棧的過程。微信

每一個棧幀分配多少內存在類結構肯定下來時就已知的,方法結束或者線程結束內存天然跟着回收了。多線程

而Java堆和方法區不同,一個接口中的多個實現類的內存可能不同,每一個方法的多個分支須要的內存也可能不同,咱們只有在程序運行時候才知道會建立哪些對象,這部份內存的分配和回收都是動態的。架構

1、判斷對象已死的算法工具

1)引用計數算法.net

給對象添加一個引用計數器,每當一個地方引用它時候,計數器就加1,當引用失效,計數器就減1;任什麼時候刻計數器爲0的對象就是不可能再被使用了。線程

這種方法實現簡單,效率高,可是它很難解決對象的循環引用問題:

public class Test {

    private static final int _1MB = 1024 *1024;

    private Object instance = null;

    public static void testGC(){
        Test objectA = new Test();
        Test objectB = new Test();

        objectA.instance = objectB;
        objectB.instance = objectA;

        objectA = null;
        objectB = null;

        // 假如這裏發生GC,objectA和objectB會不會被回收

    }
}

2)可達性分析算法

這個算法的基本思路是經過一系列稱爲「GC Roots」(一組必須活躍的引用)做爲起始點,從這些節點開始向下搜索,搜索走過的路徑稱爲引用鏈,當一個對象到GC Roots沒有任何引用鏈時候,那麼證實此對象是不可用的。

Java語言中,作做爲GC Roots的對象包括如下幾種:

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

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

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

4)本地方法棧JNI(即通常說的Native方法)引用的對象。

2、引用

不管是經過引用計數器算法判斷對象的引用數量,仍是經過可達性分析算法判斷對象引用鏈是否可達,判斷對象是否可活都離不開引用,Java中將引用分爲四種:

1)強引用(Strong Reference)

是指程序代碼中廣泛存在的,相似「Object obj = new Object()」這類的引用,只有強引用還存在對象就不會被回收。

2)軟引用(Soft Reference)

軟引用是用來描述一些還有用可是非必須的對象。對於軟引用關聯的對象,在系統將於發生內存溢出異常以前,將會把這些對象列進回收範圍中進行二次回收。

3)弱引用(Weak Reference)

也是用來描述非必須對象的,強度比軟引用還弱一些,被軟引用關聯的對象只能存活到下一次內存回收以前。

4)虛引用(Phantom Referenece)

也成爲幽靈引用和幻影引用,爲一個對象設置虛引用關聯的惟一目的就是能在這個對象被回收時收到一個系統通知。

3、生存仍是死亡

即便在可達性分析算法中不可達的對象,也並不是必定是「非死不可」的,這時候他們暫時處於「緩刑」階段,真正宣告一個對象死亡至少要經歷兩個階段:

1)若是對象在可達性分析算法中不可達,那麼它會被第一次標記並進行一次刷選,刷選的條件是是否須要執行finalize()方法(當對象沒有覆蓋finalize()或者finalize()方法已經執行過了(對象的此方法只會執行一次)),虛擬機將這兩種狀況都會視爲沒有必要執行)。

2)若是這個對象有必要執行finalize()方法會將其放入F-Queue隊列中,稍後GC將對F-Queue隊列進行第二次標記,若是在重寫finalize()方法中將對象本身賦值給某個類變量或者對象的成員變量,那麼第二次標記時候就會將它移出「即將回收」的集合。

finalize()能作的工做,使用try-finally或者其餘方式都能作到更好,更及時,因此不建議使用此方法。

4、方法區回收

永久代中回收的內容主要是兩部分:廢棄的常量和無用的類。判斷無用的類(類卸載)必須知足三個條件:

1)該類因此的實例都已經被回收

2)加載該類的ClassLoader被回收

3)該類對應的java.lang.Class對象沒有在任何地方引用,沒法在任何地方經過反射訪問該類的方法

你們能夠關注下棧長的微信公衆號:Java技術棧,回覆:福利,能夠免費獲取一份我整理的 2020 最新 Java 面試題,真的很是全(含答案),無任何套路。

推薦去個人博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、後端、架構、阿里巴巴等大廠最新面試題

以爲不錯,別忘了點贊+轉發哦!

相關文章
相關標籤/搜索