在Java中,虽然不需要程序员手动去管理对象的生命周期,但是如果希望某些对象具备一定的生命周期的话(比如内存不足时JVM就会自动回收某些对象从而避免OutOfMemory的错误)就需要用到软引用和弱引用了。
从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过代码的方式决定某些对象的生命周期;第二是有利于JVM进行垃圾回收。下面来阐述一下这四种类型引用的概念:
引用分为四个,从高到低的级别以此为强引用-软引用-弱引用-虚引用.
-
引用类型
类别 回收机制 用途 生存时间 强引用 从不回收 对象状态 JVM停止运行时 软引用 内存不足时进行回收 缓存 内存不足 弱引用 对象不被引用时回收 缓存 GC运行后 虚引用 对象被回收时 管理控制精确内存稳定性 unknown
强引用(Strong Reference)
永不回收。
强引用就是在程序代码之中普遍存在的,类似Object obj = new Object()
这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象。
弱引用(Soft Reference)
重点回收对象。
弱引用也是用来描述非必需对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。
软引用(Weak Reference)
内存将要溢出时才被回收。
软引用是用来描述一些还有用但并非必需的对象。对于软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象列表回收范围之中进行二次回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
虚引用(了解)(Phantom Reference)
虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。
常用的弱引用和软引用
比如在图片加载框架中,通过弱引用来实现内存缓存。
//实现图片异步加载的类 public class AsyncImageLoader { //以Url为键,SoftReference为值,建立缓存HashMap键值对。 private Map<String, SoftReference<Drawable>> mImageCache = new HashMap<String, SoftReference<Drawable>>(); //实现图片异步加载 public Drawable loadDrawable(final String imageUrl, final ImageCallback callback) { //查询缓存,查看当前需要下载的图片是否在缓存中 if(mImageCache.containsKey(imageUrl)) { SoftReference<Drawable> softReference = mImageCache.get(imageUrl); if (softReference.get() != null) { return softReference.get(); } } final Handler handler = new Handler() { @Override public void dispatchMessage(Message msg) { //回调ImageCallbackImpl中的imageLoad方法,在主线(UI线程)中执行。 callback.imageLoad((Drawable)msg.obj); } }; /*若缓存中没有,新开辟一个线程,用于进行从网络上下载图片, * 然后将获取到的Drawable发送到Handler中处理,通过回调实现在UI线程中显示获取的图片 */ new Thread() { public void run() { Drawable drawable = loadImageFromUrl(imageUrl); //将得到的图片存放到缓存中 mImageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); Message message = handler.obtainMessage(0, drawable); handler.sendMessage(message); }; }.start(); //若缓存中不存在,将从网上下载显示完成后,此处返回null; return null; } //定义一个回调接口 public interface ImageCallback { void imageLoad(Drawable drawable); } //通过Url从网上获取图片Drawable对象; protected Drawable loadImageFromUrl(String imageUrl) { try { return Drawable.createFromStream(new URL(imageUrl).openStream(),"debug"); } catch (Exception e) { // TODO: handle exception throw new RuntimeException(e); } } }
Handler 弱引用,防止内存泄漏
public class MainActivity extends AppCompatActivity { private Handler handler ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new MyHandler( this ) ; new Thread(new Runnable() { @Override public void run() { handler.sendEmptyMessage( 0 ) ; } }).start() ; } private static class MyHandler extends Handler { WeakReference<MainActivity> weakReference ; public MyHandler(MainActivity activity ){ weakReference = new WeakReference<MainActivity>( activity) ; } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if ( weakReference.get() != null ){ // update android ui } } } }