Java清除:收尾和垃圾收集

FrankYou發表於2016-10-20

垃圾收收集器(GC)只知道釋放由new關鍵字分配的記憶體,所以不知道如何釋放物件的“特殊”記憶體。為了解決這個問題,Java提供了一個名為:finalize()的方法,可為我們的類定義它。

理想情況下finalize()方法的工作原理是這樣:一旦CG準備好釋放物件佔用的記憶體空間,它首先呼叫finalize()方法,而且只有在下一次的垃圾收集過程中,才會真正回收物件的記憶體。

GC != Destructor,垃圾收集器並不等於破壞器。

為強制進行收尾工作(執行除釋放物件儲存空間之外的其它某種形式的清除工作),可先呼叫System.gc(),再呼叫System.runFinalization()這樣可清除到目前為止沒有使用的所有物件。這樣做一個稍顯奇怪的地方是在呼叫runFinalization()之前呼叫gc(),這看起來似乎與Sun公司的文件說明有些牴觸,它宣稱首先執行收尾模組,再釋放儲存空間。然而,若在這裡首先呼叫runFinalization(),再呼叫gc(),收尾模組根本不會執行。

針對所有物件,Java1.1有時之所以會預設為跳過收尾工作,是由於它認為這樣做的開銷太大。不管用哪種方法強制進行垃圾收集,都可能注意到比沒有額外收尾工作時較長的時間延遲

finalize()最有用處的地方之一是觀察垃圾收集的過程

public class Garbage {
    public static void main(String[] args) {

        while (!Chair.f) {
            new Chair();
            new String("To take up space");
        }

        System.out.println("After all Chairs have been created:\n" + "total created = " + Chair.created + ", total finalized = " + Chair.finalized);

        System.out.println("gc():");
        System.gc();
        System.out.println("runFinalization():");
        System.runFinalization();

        System.out.println("bye!");
    }
}

public class Chair {
    static boolean gcrun = false;
    static boolean f = false;
    static int created = 0;
    static int finalized = 0;
    int i;

    public Chair() {
        i = ++created;
        if (created == 47){
            System.out.println("Created 47");
        }
    }

    protected void finalize(){
        if (!gcrun){
            gcrun = true;
            System.out.println("Beginning to finalize after chairs been created.");
            System.out.println("i=" + i);
            System.out.println("created=" + created);
        }
        if (i == 47){
            System.out.println("Finalize chair #47,setting flag to stop chair creation.");
            f = true;
        }
        finalized++;
        if (finalized >= created){
            System.out.println("All finalized.");
        }
    }
}

相關文章