Last active
August 29, 2015 14:25
-
-
Save xinghui/bf39cde8b4d9b7ede8c5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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