定义:弱引用,与强引用(我们常见的引用方式)相对;特点是:GC在回收时会忽略掉弱引用对象(忽略掉这种引用关系),即:就算弱引用指向了某个对象,但只要该对象没有被强引用指向,该对象也会被GC检查时回收掉。
强引用实例自然不会被GC回收!
如何引出弱引用?弱引用的实际用途是什么?
什么是内存泄漏?Java使用有向图机制,通过GC自动检查内存中的对象;如果GC发现一个或一组对象为不可达的状态,则将该对象从内存中回收。也就是说:一个对象不被任何引用所指向,则该对象会在被GC发现的时候回收。
可能导致内存泄漏的实例:
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mImageView.setImageBitmap(mBitmap);
};
};
当使用内部类(或者匿名类)来创建Handler的时候,Handler对象会隐式地持有一个外部类的对象(通常是Activity)的引用(否则怎么可能通过Handler来操作Activity的View?)。而Handler通常会伴随着一个耗时的后台线程(比如:拉取网络图片);该后台线程在任务执行完毕后,通过消息机制通知Handler,然后Handler把图片更新到界面上。假设用户在网络请求过程中关闭了Activity,正常情况下这个Activity不再被使用,就有可能被GC回收;但此时线程尚未执行完毕,而该线程持有Handler的引用(不然怎么发送消息给Handler?),Handler又持有Activity的引用,就导致该Activity无法被回收(内存泄漏),直到网络请求结束(如:图片下载完毕)。另外如果执行了Handler的postDelayed(),该方法会将Handler装入一个Message,并把该Message推到MessageQueue中,由此产生了一条链式结构:MessageQueue->Message->Handler->Activity,导致Activity被持有引用而无法被回收。(总结:实例对象被其他对象持有引用,而无法被回收)
内存泄漏的危害是什么?内存泄漏会引发虚拟机占用内存过高。对于Android应用程序来说,用户打开一个Activity,使用完之后关闭,内存泄漏;执行上述步骤多次,程序占用内存超过系统限制。
如何避免内存泄漏?可以使用什么方法?由此引出了弱引用。
用于非必需对象,被弱引用关联的对象只能生存到下一次GC发生之前。当GC工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
/**
* <功能描述> 用于加载Bitmap实例
*
* @author Administrator
*/
public class AsyncDrawable extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
public AsyncDrawable(Resources res, Bitmap bitmap,
BitmapWorkerTask bitmapWorkerTask) {
super(res, bitmap);
// bitmapWorkerTaskReference实例关联BitmapWorkerTask
bitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(
bitmapWorkerTask);
}
public BitmapWorkerTask getBitmapWorkerTask() {
return bitmapWorkerTaskReference.get();
}
}
此时 WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference 关联了 bitmapWorkerTask 实例(可认为两者是“好朋友”关系);在虚拟机看来 bitmapWorkerTask 实例是垃圾时,但 WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference 不是垃圾。但垃圾并不会立即被回收,也就是仍然可以使用对象 bitmapWorkerTask 实例;若该对象已被清理,则必须重新构建对象,并再一次关联。
好处在于:可以申请任意多个 bitmapWorkerTask 实例对象,并与弱引用对象关联;使用前,先判断是否已被释放;如果已被释放,则重新申请;若未被释放,则直接使用。WeakReference负责了释放规则。
使用了上述代码后,用户在关闭Activity之后,就算后台线程还没有结束,但由于仅有一个来自Handler的弱引用指向Activity,所有GC仍然会在检查的时候把Activity回收掉。
分享到:
相关推荐
.NET中提供了WeakReference来实现。弱引用可以让您保持对对象的引用,同时允许GC在必要时释放对象,回收内存。对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望GC必要...
Java中的弱引用具体指的是java.lang.ref.WeakReference类,我们首先来看一下官方文档对它做的说明: 弱引用对象的存在不会阻止它所指向的对象变被垃圾回收器回收。弱引用常见的用途是实现规范映射...
主要介绍了Java弱引用(WeakReference)的理解与使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
SoftReference、WeakReference和PhantomRefrence分析和比较
这个项目为万能的(有时是可怕的)弱引用实现了一个kotlin包装器,以便您可以更友好地使用它们。
很早Java API就添加了弱引用(WeakReference)和软引用(SoftReference),但并不是所有的程序员都熟悉这两个概念
前述:除了强引用外,其他引用不是我们所常见的 new出来的对象,而是需要借用3个类SoftReference软引用,WeakReference弱引用,PhantomReference虚引用 1.强引用 概述:即发生OOM(Out Of Memory)内存空间满了也...
1.强引用1.强引用 2.软引用(SoftReference) 3.弱引用(WeakReference) 4.虚引用(PhantomReference) 等等;
弱引用分配工具当由于大量弱引用计数而导致垃圾回收时间过长时,通常很难确定这些弱引用在您的环境中来自何处。 这是对 java.lang.ref.WeakReference 实现的修改,它将通过 JMX MBean 跟踪和报告它发现的内容。如何...
该单元背后的思想是提供与Delphi中引用计数对象类似的生命周期,就像WeakReference在.NET中一样。 当涉及循环引用时,delphi中引用计数的对象有一些限制,例如TParent引用它的子对象(通过IChild),而TChild引用...
3.1 强引 3.2 软引 3.3 弱引 3. 4 假象引
AsyncTask_WeakReference
弱是一些有用的弱引用类型的集合。 安装 可通过NuGet获得弱点: PM>安装软件包 内容 建筑商 为以下内容创建编译的表达式: Builder.DynamicDelegate创建MethodInfo.Invoke的编译版本 Builder.OpenAction创建开放的...
import java.lang.ref.WeakReference; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; ...
还描述了Weak引用和Strong引用在android中的使用,并解决了内存泄漏的问题。 使用主要活动的弱引用,因此即使asyncTask正在运行但主机活动已被破坏,也不会发生内存泄漏。 还使用异步任务的task.cancel()方法取消...
他们分别是强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference)以及PhantomReference(虚引用),他们被 GC回收的可能性从小到大排列。 强引用(StrongReference) 只要强引用存在,垃圾回收器将...
StrongReference,SoftReference, WeakReference的使用实例,请参照博客:http://blog.csdn.net/To_be_Designer/article/details/72673421
常见的面试中会有这么一道题,“谈谈强引用、 软引用、 弱引用、虚引用”。 A:强引用,通过new出来的都是强引用 Q:那弱引用呢? A:通过WeakReference构造出的,不再有强引用… Q:那软引用呢,这些...