呼叫System.gc沒有立即執行的解決方法

曾燕輝發表於2018-06-25

轉載自:https://blog.csdn.net/yewei02538/article/details/52386642

檢視原始碼

當我們呼叫System.gc()的時候,其實並不會馬上進行垃圾回收,甚至不一定會執行垃圾回收,檢視系統原始碼可以看到

    /**
     * Indicates to the VM that it would be a good time to run the
     * garbage collector. Note that this is a hint only. There is no guarantee
     * that the garbage collector will actually be run.
     */
    public static void gc() {
        boolean shouldRunGC;
        synchronized(lock) {
            shouldRunGC = justRanFinalization;
            if (shouldRunGC) {
                justRanFinalization = false;
            } else {
                runGC = true;
            }
        }
        if (shouldRunGC) {
            Runtime.getRuntime().gc();
        }
    }

也就是justRanFinalization=true的時候才會執行 

查詢發現當呼叫runFinalization()的時候justRanFinalization變為true 
下面是runFinalization()的原始碼

/**
* Provides a hint to the VM that it would be useful to attempt
* to perform any outstanding object finalization.
*/
public static void runFinalization() {
        boolean shouldRunGC;
        synchronized(lock) {
            shouldRunGC = runGC;
            runGC = false;
        }
        if (shouldRunGC) {
            Runtime.getRuntime().gc();
        }
        Runtime.getRuntime().runFinalization();
        synchronized(lock) {
            justRanFinalization = true;
        }
}
其實當我們直接呼叫System.gc()只會把這次gc請求記錄下來,等到runFinalization=true的時候才會先去執行GC,runFinalization=true之後會在允許一次system.gc()。之後在call System.gc()還會重複上面的行為。 
所以System.gc()要跟System.runFinalization()一起搭配使用才好。 

檢視ZygoteInit.java 裡面 gc()和runFinalizationSync()是配合使用的,這樣才有效果

static void gcAndFinalize() {
    final VMRuntime runtime = VMRuntime.getRuntime();

    /* runFinalizationSync() lets finalizers be called in Zygote,
    * which doesn't have a HeapWorker thread.
    */
    System.gc();
    runtime.runFinalizationSync();
    System.gc();
}

解決方案

由此可見,當我們需要呼叫的System.gc()的時候 要這樣才會執行

System.gc();
runtime.runFinalizationSync();
System.gc();



相關文章