美文网首页
Android强引用、弱引用、软引用

Android强引用、弱引用、软引用

作者: VitaAin | 来源:发表于2019-06-12 22:23 被阅读0次
    四种引用对比.png

    一、强引用

    一个对象若持有强引用,垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。

    特点:
    • 强引用可以直接访问目标对象。
    • 强引用所指向的对象在任何时候都不会被系统回收。JVM宁愿抛出OOM异常,也不会回收强引用所指向的对象。
    • 强引用可能导致内存泄露。

    java.lang.ref包中提供了几个类:SoftReference、WeakReference、PhantomReference,分别代表软引用、弱引用、虚引用。
    ReferenceQueue类表示引用队列,它可以和这三种引用类联合使用,以便跟踪Java虚拟机回收所引用的对象的活动。


    二、软引用(SoftReference)

    软引用是除了强引用外,最强的引用类型。可以通过java.lang.ref.SoftReference使用软引用。

    用法:

    XXX xxx = new  XXX();
    SoftReference ref = new SoftReference(xxx);
    XXX anotherXXX = (XXX)ref.get();
    

    如果一个对象持有软引用,那么如果内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。

    软引用可用来实现内存敏感的高速缓存。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。

    ReferenceQueue queue = new  ReferenceQueue();
    SoftReference  ref = new  SoftReference(xxx, queue);
    

    利用ReferenceQueue.poll()方法,可以检查哪个SoftReference所软引用的对象已经被回收。于是可以把这些失去软引用的对象的SoftReference对象清除掉。常用的方式为:

    SoftReference ref = null;
    while ((ref = (EmployeeRef) q.poll()) != null) {
      // 清除ref
    }
    
    示例
    Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
    Drawable drawable = new BitmapDrawable(bitmap);
    SoftReference<Drawable> drawableSoftReference = new SoftReference<Drawable>(drawable);
    Drawable bgDrawable = drawableSoftReference.get();
    if(bgDrawable!= null) {
      view.setBackground(bgDrawable);
    }
    

    通过软引用的get()方法,取得drawable对象实例的强引用,发现对象被未回收。在GC在内存充足的情况下,不会回收软引用对象。

    在实际中,会一起从网络请求多个图片,这时就会请求非常多的内存空间,导致内存吃紧,系统开始GC。GC后,drawables.get()不再返回Drawable对象,而是返回null,这时屏幕上背景图不显示,在系统内存紧张的情况下,软引用被回收。

    使用软引用以后,在OutOfMemory异常发生之前,这些缓存的图片资源的内存空间可以被释放掉的,从而避免内存达到上限,避免Crash发生。

    注意

    在垃圾回收器对Java对象回收前,SoftReference类所提供的get方法会返回Java对象的强引用,一旦垃圾线程回收该Java对象之后,get方法将返回null。所以在获取软引用对象的代码中,一定要判断是否为null,以免出现NullPointerException导致应用崩溃。


    三、弱引用(WeakReference)

    用法:

    WeakReference<XXX> sr = new WeakReference<XXX>(new XXX());
    

    如果一个对象持有弱引用,那么在垃圾回收器线程扫描的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

    弱引用也可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

    弱引用与软引用的根本区别:

    只具有弱引用的对象拥有更短暂的生命周期,可能随时被回收;
    而只具有软引用的对象只有当内存不够的时候才被回收,在内存足够的时候,通常不被回收。

    使用场景:

    Handler中的使用,防止内存泄露。

    软引用、弱引用都非常适合来保存那些可有可无的缓存数据。如果这样做,当系统内存不足时,这些缓存数据会被回收,不会导致内存溢出。而当内存资源充足时,这些缓存数据又可以存在相当长的时间。

    如何选择软引用、弱引用?

    • 如果只是想避免OutOfMemory异常的发生,则可以使用软引用。
    • 如果对于应用的性能更在意,想尽快回收一些占用内存比较大的对象,则可以使用弱引用。
    • 还可以根据对象是否经常使用来判断。如果该对象可能会经常使用的,就尽量用软引用;如果该对象不被使用的可能性更大些,就可以用弱引用。
    • 另外,和弱引用功能类似的是WeakHashMap。WeakHashMap对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的回收,回收以后,其条目从映射中有效地移除。WeakHashMap使用ReferenceQueue实现的这种机制。

    四、虚引用(PhantomReference)

    虚引用是所有引用类型中最弱的一个。

    一个持有虚引用的对象,和没有引用几乎是一样的,随时都可能被垃圾回收器回收。当试图通过虚引用的get()方法取得强引用时,总是会失败。并且,虚引用必须和引用队列一起使用,它的作用在于跟踪垃圾回收过程。

    当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在垃圾回收后,销毁这个对象,将这个虚引用加入引用队列。

    相关文章

      网友评论

          本文标题:Android强引用、弱引用、软引用

          本文链接:https://www.haomeiwen.com/subject/eaarfctx.html