Java基础3:强引用、软引用、弱引用、虚引用

前言:Java中没有指针的概念,因为Java认为对指针的误操作会引起内存的外溢,而且对指针的管理应该是虚拟机本身的事情,而和程序无关。Java虚拟机会对引用对象的次数做出管理,并决定对那些引用次数变为零的对象在适当的时候做出回收释放内存的操作即垃圾回收。

引用存储指向对象的内存地址,是用来操纵对象的途径。Java中有个java.lang.ref包,这里面都是描述引用对象的,包括了Reference,SoftReference,WeakReference和PhantomReference。其中,Reference是基类其他三个类的基类。

引用是关系JVM垃圾回收的。垃圾回收器对于不同的引用类型有着不同的处理方式,了解这些处理方式有助于我们避免写出会导致内存泄露(OutOfMemory)异常的代码。





一、强引用(Strong References)

1、强引用是使用最普遍的引用,就是普通new对象的引用。

  User user = new User();//强引用



2、如果对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,JVM宁愿抛出OutOfMemoryErrory异常使程序异常终止,也不会去回收该对象。如果不使用时可以显示设置user = null(原来强引用的一个对象,被转成一个弱引用来指向来弱化引用,然后System.gc()方法通知gc线程,帮助垃圾回收器回收此对象,而gc具体什么时候收集这要取决于gc的算法。





二、弱引用(Weak Reference)

1、弱引用就是不是那种用强制的方式要求对象存在于内存的引用。如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,就可以用软引用。  

2、弱引用的对象比软引用的对象的生命周期更短暂当JVM进行垃圾回收时,只要扫描到,无论内存是否充足(与软引用的区别),都会回收被弱引用关联的对象但由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。

  用java.lang.ref.WeakReference类来表示:
  WeakReference wr = new WeakReference(new User());
  System.out.println(wr.get());//wr.get()来获取new User()的对象
  System.gc(); //通知JVM的gc进行垃圾回收
  System.out.println(wr.get());




三、软引用(Soft Reference)


1、我们可以把软引用理解成一种稍强的弱引用。软引用指向的对象一般会比弱引用的存活时间长些,直到JVM内存不够的时候才会被回收。我们调用System.gc()方法只是起通知作用,JVM什么时候扫描回收对象是JVM自己的状态决定的。就算扫描到软引用对象也不一定会回收它,唯有内存不够的时候才会回收。用java.lang.ref.SoftReference类来表示。软引用可用来实现内存敏感的缓存。

  String str = new String("666"); //强引用

  SoftReference softRef = new SoftReference(str);//软引用 

2、软引用可以和引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,JVM就会把这个软引用加入到与之关联的引用队列中。因为SoftReference本身也是new了一个对象,当他把别人的问题解决以后,也需要把自己的问题解决,所以当JVM把软引用对象回收后,就会把自己的对象引用放到这个队列中,只要定期的来处理一下这个ReferenceQueue就可以了。

  ReferenceQueue queue = new ReferenceQueue();
  User user = new User();
  SoftReference ref=new SoftReference(user, queue);

3、软引用在实际中有重要的应用,例如浏览器的后退按钮。按后退时,这个后退时显示的网页内容是重新进行请求还是从缓存中取出呢?这就要看具体的实现策略了。

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

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

[java]  view plain  copy
 print ?
  1. Browser prev = new Browser();               // 获取页面进行浏览  
  2. SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用         
  3. if(sr.get()!=null){   
  4.     rev = (Browser) sr.get();           // 还没有被回收器回收,直接获取  
  5. }else{  
  6.     prev = new Browser();               // 由于内存吃紧,所以对软引用的对象回收了  
  7.     sr = new SoftReference(prev);       // 重新构建  
  8. }  

  9. 这样就很好的解决了实际的问题。



四、虚引用(Phantom Reference)

1、顾名思义,就是形同虚设。如果对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收虚引用和前面的软引用、弱引用不同,它并不影响对象的生命周期。虚引用主要用来跟踪对象被垃圾回收器回收的活动。在java中用java.lang.ref.PhantomReference类表示。

  ReferenceQueue queue = new ReferenceQueue();
  PhantomReference pr = new PhantomReference(new User(),queue);
  System.out.println(pr.get());

2、注意:虚引用必须和引用队列联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。


五、总结:

1、强引用、软应用、弱应用影响对象的生命周期(对象在内存中的存活时间),虚引用无影响

2、Java 4种引用的级别由高到低依次为:

强引用 > 软引用 > 弱引用 > 虚引用

3、当垃圾回收器回收时,某些对象会被回收,某些不会被回收。垃圾回收器会从根对象Object来标记存活的对象,然后将某些不可达的对象和一些引用的对象进行回收:

Java基础3:强引用、软引用、弱引用、虚引用_第1张图片


六、参考文献,感谢前辈


Java 7之基础 - 强引用、弱引用、软引用、虚引用


Android中的引用类型(强引用,弱引用,软引用,虚引用)





你可能感兴趣的:(Java)