Skip to content

Instantly share code, notes, and snippets.

@xinghui
Last active August 29, 2015 14:25
Show Gist options
  • Save xinghui/bf39cde8b4d9b7ede8c5 to your computer and use it in GitHub Desktop.
Save xinghui/bf39cde8b4d9b7ede8c5 to your computer and use it in GitHub Desktop.
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;
/**
* https://github.com/square/leakcanary 中判断是否有内存泄漏的原理。
*
* 原理:利用Android的Application的android.app.Application.
* ActivityLifecycleCallbacks回调跟踪Activity的生命周期,
* 在有android.app.Application.ActivityLifecycleCallbacks
* .onActivityDestroyed(Activity)的时候把Activity对象添加到java.lang.ref.WeakReference中,
* 当添加的对象变为弱引用就会添加到'java.lang.ref.WeakReference.WeakReference(T,
* ReferenceQueue<? super T>)'的第二个参数,弱引用队列 中。 利用
* 'WeakReference'的这一特性,在有onActivityDestroyed回调时,通过Runtime.getRuntime().gc()去通知系统gc,
* 等待100ms
* ,然后通过java.lang.System.runFinalization()方法,强制调用已经没有被引用的对象的java.lang.Object
* .finalize()方法。
* 检查WeakReference的第二个参数ReferenceQueue队列,取出这个要检查的Activity是否已经变成弱引用。
* 如果存在于队列中,则说明:当前对象已变成弱引用,内存可以成功释放,也就不会有内存泄漏的问题
* 如果没有存在于队列中,则说明:当前对象目前还被其他对象保持持有关系(有其他对象指向要释放的对象),没有按预期释放当前对象,代表这个对象被泄漏了
* 这种情况积累下来,就会带来OutOfMemoryError。
*
* @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()是有区别的;
* @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();// 通知系统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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment