1. 程式人生 > >JVM·垃圾收集器與內存分配策略之對象是否可被回收!

JVM·垃圾收集器與內存分配策略之對象是否可被回收!

pri 計數 isalive 第一次 lis 不同的 protect live() null

1、判斷對象已經死去/不再被引用。 1.1、引用計數算法:給對象添加引用計數器,有個地方引用就+1,引用失效就-1。任何時刻,引用為0,即判斷對象死亡。 1.1.1、優點:實現簡單,效率高。 1.1.2、缺點:在主流的Java虛擬機中不被使用,因為很難解決對象之間相互循環引用的問題。 1.2、可達性分析算法(Java,C#,lisp):從一系列稱為“GC Roots”的對象作為起始點,從這些節點往下搜索,搜索走過的路徑稱為引用鏈,當沒有引用鏈可達到某對象時,認為該對象不可到達,即此對象沒有被有效引用。 1.2.1:
可做為GC Roots的對象: 虛擬機棧中引用的對象 方法區中類靜態屬性引用的對象 方法區中常量引用的對象 本地方法棧中JNI(Native方法)應用的對象 2、如何判斷是否要被回收 在Java中,采用可達性分析算法。即使判斷未不可達的對象,也不會立即宣告對象死亡。在此之前要經過至少兩次標記: 2.1、第一次標記和篩選:當第一次判斷該對象不可達(沒有與GC Roots相連的引用鏈)時,進行篩選:是否要執行finalize()方法。 2.2、第二次:
需要finalize()方法的對象會在一個低優先級的F-Queue中排隊執行finalize()。如果在finalize()方法中拯救自己,那麽就不會死。否則,被回收。 在finalize()方法中拯救自己:在改方法中重新連接上GC Roots(重新擁有連接GC Roots的引用) 2.3、總結:對象可以在被GC時自我拯救。這種拯救只有一次機會,因為GC只會調用一次對象的finalize()方法。 附自我拯救代碼:
**
* Created by KEY on 2017/12/4.
*/
public class FinalizeEscapeGC {
    public static FinalizeEscapeGC SAVA_HOOK = null;

    public void isAlive(){
        System.out.println("yes, I am still alive");
        }
    @Override
    protected void finalize() throws Throwable{
        super.finalize();
        System.out.println("finalize method executed");
        FinalizeEscapeGC.SAVA_HOOK = this;
    }

    public static void main(String[] args) throws Throwable{
        SAVA_HOOK = new FinalizeEscapeGC();

        //對象第一次拯救自己
        SAVA_HOOK = null;
        System.gc();
        //因為finalize優先級很低,所以等他0.5s
        Thread.sleep(500);
        if(SAVA_HOOK != null){
            SAVA_HOOK.isAlive();
        }else{
            System.out.println("no,I am dead :(");
        }

        //重復以上代碼,看是否能第二次拯救自己
        //對象第一次拯救自己
        SAVA_HOOK = null;
        System.gc();
        //因為finalize優先級很低,所以等他0.5s
        Thread.sleep(500);
        if(SAVA_HOOK != null){
            SAVA_HOOK.isAlive();
        }else{
            System.out.println("no,I am dead :(");
        }
    }
}

  

3、方法區的垃圾回收 說明:虛擬機規範對於方法區的實現並沒有要求是否回收,也沒有要求如何回收,甚至沒有要求具體的內存定義, 只需要滿足方法區規範即可。所以方法區的回收再不同的虛擬機有不同的實現 方法區的回收主要針對“廢棄常量”和“無用的類”。如何判斷是否是“無用的類” a.該類所有的實例都已經被回 b.加載該類的ClassLoader被回收 c.該類對應的java.lang.class對象沒有在任何地方被引用,無法再任何地方通過反射訪問該類的方法。

JVM·垃圾收集器與內存分配策略之對象是否可被回收!