查看源碼
當我們調用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()
的時候 要這樣才會執行
// 強制調用gc釋放內存 System.gc(); System.runFinalization();