在看square leakcanary源碼時,發現這樣一段話:
到底有什麼不一樣呢?
我看了手頭的4.2.2以及openjdk的源碼:
system.gc()的實作就是調用runtime.getruntime().gc(),是以兩者是等價的。是以這裡是否是作者多慮了呢?我又看了一下5.0的源碼,果然不一樣了:
這樣改之後,單純調用system.gc()是不會觸發runtime.getruntime().gc()的。但是會把這次嘗試紀錄下來,等到下次調用system.runfinalization()時,會先執行這個runtime.getruntime().gc()。
這樣改後的影響至少有兩點:
1.單純調用system.gc()是不會觸發runtime.getruntime().gc()的,直到調用了system.runfinalization()
2.system.gc() -> system.gc() -> … -> system.gc() ->system.runfinalization(),最終隻會調用一次runtime.getruntime().gc()
為什麼要這樣改呢?
找到了這個commit,是這樣描述的:
avoid running runtime.gc() until we need to run finalization. this prevents excessive explicit gc which are called from apps to get good gc behavior on dalvik. calling system.gc() does not help on art since gc for alloc is much rarer. if running finalizers is requested following a system.gc we remember that a gc was requested and perform it ahead of finalization. bug: 12004934
從這裡可以得到兩點資訊:
1.首先這是為了修複一個bug 12004934,具體什麼bug找不到了
2.其次在art模式下,直接調用gc的效果不大。至于為什麼,還沒有深入進去了解,這是art相關的另外一個專題了,後面再詳細跟進。
回到開頭,leakcanary的作者在這裡直接用了runtime.getruntime().gc()的确是有理由的,但是這應該不是最好的方式,因為從這個送出的描述來看,連續調用runtime.getruntime().gc()可能存在bug。修改後的模式是gc / finalization / gc,雖然leakcanary這裡的使用不會有問題。但是我覺得我們自己使用的話,用system.gc() 配合 system.runfinalization()會比較好。