关于强引用,软引用,弱引用,虚引用(Strong references, Soft references, Weak references, Phantom references)

读《java性能权威指南》时,读到了关于强引用,软引用,弱引用,虚引用的介绍。

读完介绍后,又找了一些网上的资料,唯一感到困惑的就是,在什么场景使用?如何使用?

接下来先把从书上读到的,和在网上找到的内容进行一下总结:

1,强引用(Strong references)

例子:

  Object strongReference = new Object();

说明:

  强引用是我们一般最常的方式。在只要strongReference没有脱离作用域,或没有被设置成null,GC都不会回收它。

回收时机:

  (1)脱离作用域:例如,对象被声明在方法内部,方法执行完后。

  (2)被设置成null


2,软引用(Soft references)

例子:

  Object softReferenceObj = new Object();
  SoftReference softRerference = new SoftReference(softReferenceObj);

说明:

  它的使用需要用套在SoftReference中使用。放到SoftReference中,然后把原来的引用设置成null,才有机会被回收。

  使用被做为软引用的对象时,先要用SoftReference的get方法来看对象是否被回收。如果返回值为null,那对象已经被回收了。


  看一些资料上说,软引用非常适合用来做cache,因为它的回收机制是:会尽可能长的保留引用直到 JVM 内存不足时才会被回收。

  但“JVM内存不足”是怎么个不足,没有详细说明。《java性能权威指南》详细介绍了一下:

  假设堆空间为4G,在Full GC后,堆空间还剩1G,那么如果在过去的1024000(1024x1000)秒内没有访问软引用的话,

  GC执行时就会回收它。在没有经过上面的时间之前,即使有GC执行,也不会回收它。

  上面的1024是1G的剩余空间变过来的,1000这个值可通过JVM参数(SoftReflRUPolicyMSPerMB)进行调整,

  默认值就是1000。上面是对“JVM内存不足”的解释,如果要让GC回收它,必须让这个引用没有强引用,例如:softReferenceObj = null;


  但问题是,在什么场景,如何利用这个特性进行设计和运用。因为,这种cache机制建出来的cache,无法控制它,

  你不知道何时它就被清理掉了。但它的好处也在于此,不用你自己清理,一般的对象池,需要你自己清理和维护。

  如何使用还需要发掘。。。

回收时机:

  (1),引用被设置成null

  (2),并且,堆的剩余空间*SoftReflRUPolicyMSPerMB值的这么多的时间过去时,还没有被访问。


3,弱引用(Weak references)

例子:

  // 也可以用上面的软引用的方式,没有区别

  WeakReference weakReference = new WeakReference(new Object());

说明:

  弱引用和软引用没有太大的区别,唯一的区别就是不会像软引用那样,在一定时间没有被访问后,才会被回收,而是只要有GC执行,就会回收。

回收时机:

  (1),引用被设置成null

  (2),有GC执行


4,虚引用(Phantom references)

例子:

  ReferenceQueue queue = new ReferenceQueue();
  PhantomReference phantomReference= new PhantomReference(new Object(), queue);

说明:

  虚引用和弱引用非常相似,但不同的一点是,  用PhantomReference的get方法时,返回值永远为null,也就是说你永远无法通过

  PhantomReference来得到它的引用。而且它必须和ReferenceQueue一起使用,当垃圾收集器确定了某个对象是虚可及对象时,

  PhantomReference 对象就被放在它的 ReferenceQueue 上。

  还有一个不同点是,放入RererenceQueue的时机。当弱引用一旦达到可以被回收的状态时,就会被加入到队列里。但这种状态的对象

  可能会因为对象的finalize()方法里“复活”(或者说回收的更慢)。而PhantomReference对象被放到RererenceQueue的时候,

  实际上它已经被从物理内存里清除掉了。它的get方法永远返回null,也防止你”复活“它(或者说妨碍它被释放掉)

  问题来了,那我们能用它来做什么呢?看了一些文章,有两个地方可用

    1,通过ReferenceQueue,跟踪对象什么时候被释放,或者在它被释放后,做一些后续工作。

    2,避免因为finalize()方法造成很久才能释放。原因如下:实现了finalize()方法的对象,至少要经过两个GC周期才能被释放。

         具体说明参看下面的文章:

           http://www.infoq.com/cn/articles/jvm-source-code-analysis-finalreference

           https://www.ibm.com/developerworks/cn/java/j-lo-langref/

           https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

回收时机:

  (1),引用被设置成null

  (2),有GC执行


另外还有RererenceQueue,WeakHashMap,这里不多说了,在下面参考的文章写的都挺好的,大家可以自己的看一下。


参考文章:

http://blog.csdn.net/mxbhxx/article/details/9111711(原文:http://www.iteye.com/topic/401478)

http://www.cnblogs.com/skywang12345/p/3154474.html

https://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

http://www.infoq.com/cn/articles/jvm-source-code-analysis-finalreference

http://puretech.iteye.com/blog/2008663


http://blog.csdn.net/huoyin/article/details/5891998


你可能感兴趣的:(java)