歡迎訪問Android日記,如有轉(zhuǎn)載請注明Android日記 http://androiddiary.site
2016.12.31 周六 晴 杭州
記錄今天值得閱讀的文章:
寫日記
由于想主動(dòng)的通過代碼觸發(fā)gc測試軟引用與弱引用的不同表現(xiàn)擅这,很自然我就想到了去調(diào)用System.gc();既然用到了這個(gè)函數(shù)我就想去看看這個(gè)函數(shù)是怎么樣實(shí)現(xiàn)的
/** * Runs the garbage collector.
* Calling the gc method suggests that the Java Virtual
* Machine expend effort toward recycling unused objects in order to
* make the memory they currently occupy available for quick reuse.
* When control returns from the method call, the Java Virtual
* Machine has made a best effort to reclaim space from all discarded
* objects.
* The call <code>System.gc()</code> is effectively equivalent to the
* call: Runtime.getRuntime().gc()
* * @see java.lang.Runtime#gc()
*/
public static void gc() {
boolean shouldRunGC;
synchronized (LOCK) {
shouldRunGC = justRanFinalization;
if (shouldRunGC) {
justRanFinalization = false;
} else {
runGC = true;
}
}
if (shouldRunGC) {
Runtime.getRuntime().gc();
}
}
突然感覺有點(diǎn)不對呢螃概,印象中文檔都說和直接調(diào)用Runtime.getRuntime().gc();一樣的
并且在jdk中也是直接調(diào)用的實(shí)現(xiàn)箩绍。所以由此而想到Google應(yīng)該是在某個(gè)版本更改了Android中的實(shí)現(xiàn)。經(jīng)過查看api19也就是Android 4.4還是沒有變化的
/**
* 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() {
Runtime.getRuntime().gc();
}
而在Android 5.0(API21)之后也就變成了一開始提到的樣子句各。
具體分析一下Google對System.gc()進(jìn)行了怎樣的改變,調(diào)用System.gc只有當(dāng)justRanFinalization 為true的時(shí)候才執(zhí)行一次Runtime.getRuntime().gc();也就是說連續(xù)多次調(diào)用時(shí)不能全部都生效的剔蹋,再看看justRanFinalization 是啥時(shí)候改變的
/**
* Runs the finalization methods of any objects pending finalization.
* <p>
* Calling this method suggests that the Java Virtual Machine expend
* effort toward running the <code>finalize</code> methods of objects
* that have been found to be discarded but whose <code>finalize</code>
* methods have not yet been run. When control returns from the
* method call, the Java Virtual Machine has made a best effort to
* complete all outstanding finalizations.
* <p>
* The call <code>System.runFinalization()</code> is effectively
* equivalent to the call:
* Runtime.getRuntime().runFinalization()
* * @see java.lang.Runtime#runFinalization()
*/
public static void runFinalization() {
boolean shouldRunGC;
synchronized (LOCK) {
shouldRunGC = runGC;
runGC = false;
}
if (shouldRunGC) {
Runtime.getRuntime().gc();
}
Runtime.getRuntime().runFinalization();
synchronized (LOCK) {
justRanFinalization = true;
}
}
忽然發(fā)現(xiàn)這個(gè)除了會(huì)改變justRanFinalization 的值幅狮,在 runGC 為true時(shí)調(diào)用這個(gè)方法也會(huì)觸發(fā) Runtime.getRuntime().gc();
讓我們看看justRanFinalization的定義
/**
* Whether or not we need to do a GC before running the finalizers.
*/
private static boolean runGC;
/**
* If we just ran finalization, we might want to do a GC to free the finalized objects.
* This lets us do gc/runFinlization/gc sequences but prevents back to back System.gc().
*/
private static boolean justRanFinalization;
也就是我們 gc/runFinlization/gc 這樣調(diào)用完成一次gcAndFinalize,但是要避免多次反復(fù)的調(diào)用System.gc().
我們可以看一下ZygoteInit中的gcAndFinalize()方法中如何使用的
/**
* Runs several special GCs to try to clean up a few generations of
* softly- and final-reachable objects, along with any other garbage.
* This is only useful just before a fork().
*/
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();
}
這里的 VMRuntime.getRuntime().runFinalizationSync();的作用其實(shí)和Runtime.getRuntime().runFinalization();作用一樣闯估。Runtime.getRuntime().gc()是告訴垃圾收集器打算進(jìn)行垃圾收集,而垃圾收集器進(jìn)不進(jìn)行收集是不確定的;Runtime.getRuntime().runFinalization();強(qiáng)制調(diào)用已經(jīng)失去引用的對象的finalize方法
讓我們看一下谷歌為什么這樣修改System.gc()這個(gè)方法呢供炼?
從這個(gè)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
Change-Id: Id1343ce8b5378c5f53c1e5649c06ddd045f56a3b
從這里可以得到兩點(diǎn)信息:
1.首先這是為了修復(fù)一個(gè)bug 12004934
2.其次在art模式下一屋,直接調(diào)用gc的效果不大。
參考文章:
System.GC()并不一定執(zhí)行的原因 http://www.eoeandroid.com/thread-922938-1-1.html
Android System.gc()注意點(diǎn)
http://blog.csdn.net/fearGod/article/details/46364599