java强引用,软引用,弱引用和虚引用

Posted YUKINO62

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java强引用,软引用,弱引用和虚引用相关的知识,希望对你有一定的参考价值。

  • 强引用:之前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用,比如下面这段代码中的object和str都是强引用:

    Object object = new Object();
    String str = "StrongReference";
    

    如果一个对象具有强引用,那就类似于必不可少的物品,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

    如果想中断强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样一来的话,JVM在合适的时间就会回收该对象。

    比如ArraryList类的clear方法中就是通过将引用赋值为null来实现清理工作的:

    public void clear() 
          modCount++;
     
          // Let gc do its work
          for (int i = 0; i < size; i++)
              elementData[i] = null;
     
          size = 0;
    
    

    在ArrayList类中定义了一个私有的变量elementData数组,在调用方法清空数组时可以看到为每个数组内容赋值为null。

    这种遍历数组挨个赋值为null和直接elementData=null的区别是,clear()方法只会将list中的对象变成垃圾回收清空,但是list对象还是存在。但是通过elementData=null后,不仅列表中的对象变成了垃圾,为列表分配的空间也会回收。

  • 软引用:软引用是用来描述一些有用但并不是必需的对象,在Java中用java.lang.ref.SoftReference类来表示。对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象。

    import java.lang.ref.SoftReference;
     
    public class SoftRef   
     
        public static void main(String[] args)  
            System.out.println("start");            
            Obj obj = new Obj();            
            SoftReference<Obj> sr = new SoftReference<Obj>(obj);  
            obj = null;  
            System.out.println(sr.get());  
            System.out.println("end");     
               
      
     
    class Obj  
        int[] obj ;  
        public Obj()  
            obj = new int[1000];  
          
    
    

输出:
start
test.Obj@1f6226
end

软引用在实际中有重要的应用,例如浏览器的后退按钮,这个后退时显示的网页内容可以重新进行请求或者从缓存中取出:

(1)如果一个网页在浏览结束时就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建

(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出这时候就可以使用软引用

  • 弱引用:弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。

    弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。所以被软引用关联的对象只有在内存不足时才会被回收,而被弱引用关联的对象在JVM进行垃圾回收时总会被回收。

  • 虚引用:虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。在java中用java.lang.ref.PhantomReference类表示。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收的活动。

    虚引用必须和引用队列关联使用(ReferenceQueue),当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之 关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

    import java.lang.ref.PhantomReference;
    import java.lang.ref.ReferenceQueue;
     
     
    public class PhantomRef 
        public static void main(String[] args) 
            ReferenceQueue<String> queue = new ReferenceQueue<String>();
            PhantomReference<String> pr = new PhantomReference<String>(new String("hello"), queue);
            System.out.println(pr.get());
        
    				
    
  • 利用软引用和弱引用解决OOM问题:假如有一个应用需要读取大量的本地图片,如果每次读取图片都从硬盘读取,则会严重影响性能,但是如果全部加载到内存当中,又有可能造成内存溢出,此时使用软引用可以解决这个问题。

    设计思路是:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题。

以上是关于java强引用,软引用,弱引用和虚引用的主要内容,如果未能解决你的问题,请参考以下文章

Java基础篇 - 强引用弱引用软引用和虚引用

java对象的强引用,软引用,弱引用和虚引用

java对象的强引用,软引用,弱引用和虚引用

Java基础篇 - 强引用弱引用软引用和虚引用

Java:强引用,软引用,弱引用和虚引用

Java:强引用,软引用,弱引用和虚引用