垃圾收集器與內存分配策略

1. 引用計數GC算法算法

每一個對象都會有對應的計數器來計算對象引用,但JVM不會採用該策略,由於不能解決對象相互引用的回收。ide

public class ReferenceCountingGC {
    
    public Object instance = null;

    private static final int _1M = 1024 * 1024;
    
    private byte[] bigSize = new byte[2 * _1M];
    
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ReferenceCountingGC objA = new ReferenceCountingGC();
        ReferenceCountingGC objB = new ReferenceCountingGC();
        
        objA.instance = objB; objB.instance = objA;
        
        objA = null;
        objB = null;
        
        //GC
        System.gc();
    }

}

設置VM參數,打印GC日誌this

-XX:+PrintGC
-XX:+PrintGCDetails

部分GC日誌:spa

[GC (System.gc()) [PSYoungGen: 6758K->584K(38400K)] 6758K->592K(125952K), 0.0015223 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 584K->0K(38400K)] [ParOldGen: 8K->515K(87552K)] 592K->515K(125952K), [Metaspace: 2554K->2554K(1056768K)], 0.0048039 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

能夠從PSYoungGen中明顯看到對象被回收,也就是JVM並無採用引用計數算法。日誌

2. 可達性分析算法code

 

public class FinalizeEscapeGC {

    public static FinalizeEscapeGC instance = null;
    
    @Override
    protected void finalize() throws Throwable {
        // TODO Auto-generated method stub
        super.finalize();
        System.out.println("finalize() executed");
        FinalizeEscapeGC.instance = this;
    }
    
    
    public static void main(String[] args) throws InterruptedException {
        FinalizeEscapeGC.instance = new FinalizeEscapeGC();
        //在finalize()中拯救本身 - 成功
        instance = null;
        System.gc();
        //finalize()優先級很低,sleep
        Thread.sleep(500);
        if(instance != null) {
            System.out.println("still alive");
        }else {
            System.out.println("object recycling");
        }
        
        //再嘗試自救 - 失敗
        instance = null;        
        System.gc();
        Thread.sleep(500);
        if(instance != null) {
            System.out.println("still alive");
        } else {
            System.out.println("object recycling");
        }
    }
} 

在第一次GC時,finalize()第一次執行並將this賦予對象instance,所以this未被回收。但覆蓋的finalize()僅執行一次,所以第二次GC時,對象被回收。對象

相關文章
相關標籤/搜索