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

来源:互联网 发布:早餐吃什么 知乎 编辑:程序博客网 时间:2024/05/24 08:34

本文转自http://blog.csdn.net/kameleon2013/article/details/19182023

笔者在编写Android程序时,经常会使用到异步加载图片的机制,在这个功能中,笔者会使用到SoftReference类,也就是JAVA的软引用,另外强引用就更不用说了,用的频率更高,因此笔者结合自己的经验和查阅的资料,将JAVA中这几个不同的引用方式整理了一下,分享给阅读的同行!


在JAVA中有四种不同的引用方式

1.强引用

2.弱引用

3.虚引用

4.软引用


1.强引用

我们平常用的最多的就是强引用了,如:String s = new String("opps"),这种形式的引用称为强引用。

强引用有以下几个特点:

1)强引用可以直接访问目标对象 ;
2)强引用所指向的对象在任何时候都不会被系统回收 ;
3)由于2的原因,强引用可能导致内存泄漏。

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.kameleon.test;  
  2.   
  3. public class StrongReference {  
  4.     public static void main(String[] args){  
  5.         String str = new String("opps");  
  6.         System.gc();  
  7.         System.runFinalization();  
  8.         System.out.println(str);  
  9.     }  
  10. }  
这个是输出:


我们可以看到,垃圾回收后,依然可以打印出str所指向的opps,因此强引用所指向的对象不会被垃圾回收器回收。这样就可能会导致内存泄露。强引用指向的对象,垃圾回收器是不会自动帮你回收对象所占的内存,一旦对象被强引用,那么强引用本身就强迫这个对象保留在内存中,因此需要你自己手动去释放不需要再次别使用的对象所占的空间,这样你可能就要多次重复相同的释放内存的动作了,因为此时内存回收器不会回收强引用指向的内存空间


2.弱引用

弱引用通过weakReference类来实现的。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

我们来测试一下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.kameleon.test;  
  2.   
  3. import java.lang.ref.WeakReference;  
  4.   
  5. public class WeakReferenceTest {  
  6.     public static void main(String[] args) {  
  7.         String str = new String("opps");  
  8.         //创建一个软引用对象 指向str对象  
  9.         WeakReference<String> wr = new WeakReference<String> (str);  
  10.         str =null;  
  11.         //输出  
  12.         System.out.println(wr.get());//opps  
  13.         //强制垃圾回收  
  14.         System.gc();  
  15.         System.out.println(wr.get());//null  
  16.     }  
  17. }  
这是输出:



3.虚引用

“虚引用”顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用主要用来跟踪对象被垃圾回收器回收的活动。虚引用与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过检测与虚引用关联的虚引用队列是否已经包含了指定的虚引用,从而了解虚引用的对象是否即将被回收。

我们来测试下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.kameleon.test;  
  2.   
  3. import java.lang.ref.PhantomReference;  
  4. import java.lang.ref.ReferenceQueue;  
  5.   
  6. public class PhantomReferenceTest {  
  7.     public static void main(String[] args){  
  8.         // 创建一个对象  
  9.         String str = new String("opps");  
  10.         //  创建一个引用队列  
  11.         ReferenceQueue<String> rq = new ReferenceQueue<String>();  
  12.         //创建一个虚引用,指定引用对象.不能单独使用必须关联引用队列  
  13.         PhantomReference pr = new PhantomReference(str,rq);  
  14.         //切断强引用  
  15.         str = null;  
  16.         //试图取得虚引用对象  
  17.         System.out.println(pr.get());  
  18.         //垃圾回收  
  19.         System.gc();  
  20.         System.runFinalization();  
  21.         //取出引队列中的最先进入队列的引用与pr进行比较  
  22.         System.out.println(rq.poll()==pr);    
  23.     }  
  24. }  
这个是输出:



4.软引用

如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。我们可以尝试使用这样的命令:

java -Xmx1m -Xms1m SoftReferenceTest(这是你创建的类名)命令,强制堆内存为1M时,当你创建大量软引用对象时,如果他们的总共的大小超过了1M,软引用引用对象将被回收。软引用可用来实现内存敏感的高速缓存。


简单总结一下:

如果使用软引用,弱引用,虚引用的引用方式引用对象,垃圾回收就能够随意的释放这些对象,如果希望尽可能减小程序在其声明周期中所占用的内存大小,可以灵活使用这些引用。如果使用了这些引用就不能保留这些对象的强引用(强引用应该置null),否则就浪费了这些类提供的任何好处。



0 0
原创粉丝点击