Leakcanary作用:
判斷是否有內存泄漏;
-
定位并dump出調用棧;
利用haha庫去輸出dump信息的舆驶。
haha庫相關信息:https://github.com/square/haha
-
以圖形方式展示給開發(fā)者;
更多Leakcanary信息參考:https://github.com/square/leakcanary
今天我們主要談一下他判斷內存泄漏的方式,也就是上面的第一項筐摘。
說明:
利用
Android
中Application
的android.app.Application.ActivityLifecycleCallbacks
回調,跟蹤Activity
的生命周期壳快,在有android.app.Application.ActivityLifecycleCallbacks.onActivityDestroyed(Activity)
的回調時把Activity
對象添加到java.lang.ref.WeakReference
中老速。當添加的對象變?yōu)槿跻镁蜁砑拥?code>java.lang.ref.WeakReference.WeakReference(T, ReferenceQueue<? super T>)的第二個參數,弱引用隊列中御滩。
利用
WeakReference
的這一特性,在有onActivityDestroyed
回調時党远,通過Runtime.getRuntime().gc()
去通知系統(tǒng)gc削解,等待100ms,然后通過java.lang.System.runFinalization()
方法沟娱,強制調用已經沒有被引用的對象的java.lang.Object.finalize()
方法氛驮。-
檢查
WeakReference
的第二個參數ReferenceQueue
隊列,取出要檢查的Activity
济似。 判斷是否在隊列中:如果存在:當前對象已變成弱引用矫废,內存可以成功釋放,也就不會有內存泄漏的問題
-
如果不存在:說明當前對象目前還被其他對象保持持有關系(有其他對象指向要釋放的對象)砰蠢,沒有按預期釋放當前對象蓖扑,代表這個對象被泄漏了。這種情況積累下來台舱,就會帶來
OutOfMemoryError
律杠。?
Demo
package com.xinghui.java.weakreference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
/**
*
* @author xinghui
*
*/
public class WeakReferenceTest {
/**
* 用于看驗證效果。
* true: 最后有不能回收的內存
* false: 內存全部回收
*/
private static final boolean CONFIG_LEAK = true;
/**
* 被保留的對象列表
*/
static Set<Object> retainedObject;
static ReferenceQueue<ClassA> queue = new ReferenceQueue<ClassA>();
public static void main(String[] args) {
retainedObject = new CopyOnWriteArraySet<Object>();
ClassA mClassA = new ClassA();
ClassB mClassB = new ClassB();
mClassB.mClassA = mClassA;
if (CONFIG_LEAK) {
ClassC.container = mClassB;
}
/**
* 當mClassA變成弱引用時,會添加到queue隊列
* A WeakReference may be cleared and enqueued as soon as is known to be weakly-referenced.
*/
WeakReference<ClassA> re = new WeakReference<ClassA>(mClassA, queue);
retainedObject.add(re);
mClassA = null;
mClassB = null;
removeWeaklyReachableReferences("NONE");
/**
* 1柜去、Java中的System.gc()和Android中的System.gc()是有區(qū)別的灰嫉;
* @see 2、libcore.java.lang.ref.FinalizationTester.induceFinalization()
*
*/
// System.gc() does not garbage collect every time. Runtime.gc() is
// more likely to perfom a gc.
Runtime.getRuntime().gc();// 通知系統(tǒng)gc
try {
/*
* Hack. We don't have a programmatic way to wait for the reference queue
* daemon to move references to the appropriate queues.
*/
Thread.sleep(100);
} catch (InterruptedException e) {
throw new AssertionError();
}
System.runFinalization(); // 強制調用*已經沒有被引用的對象*的finalize方法
removeWeaklyReachableReferences("runFinalization");
if (retainedObject.size() > 0) {
for (Object o : retainedObject) {
System.out.println("++++++++++ retained Object " + o);
}
} else {
System.out.println("------------NO retained Object");
}
}
private static void removeWeaklyReachableReferences(String TAG) {
Reference<? extends ClassA> ref;
System.out.println(TAG + " start ");
while ((ref = queue.poll()) != null) {
retainedObject.remove(ref);
System.out.println("removed " + ref + " after " + TAG);
}
}
static class ClassA {
}
static class ClassB {
ClassA mClassA;
}
static class ClassC {
static ClassB container;
}
}