正确理解PhantomReference
2014-03-18 11:44
162 查看
phantom reachable - An object is not strongly, softly, nor weakly reachable, has been
determined to not be resurrectable by any finalizer (if it declares a finalize() method itself, then its finalizer will have been run), and is reachable from the roots via one or more (uncleared) phantom reference objects. As soon as an object referenced by
a phantom reference object becomes phantom reachable, the garbage collector will enqueue it. The garbage collector will never clear a phantom reference. All phantom references must be explicitly cleared by the program.
这段话说明了phantom
reachable与strongly, softly, weakly reachable的区别,不好理解的话在“if
it declares a finalize() method itself, then its finalizer will have been run“。
null
null
null
java.lang.ref.PhantomReference@10b30a7
这个结果正常,符合对PhantomReference的文档说明,PhantomReference引用的对象是unreachable的,即使未被垃圾回收器回收,通过get方法返回的也是空。接下来修改一下上面的实例:
null
null
======================
null
null
上一段代码唯一的区别就是F类重载了finalize方法,重载之后通过gc回收后,却没有加入到ReferenceQueue之中。然后再稍微修改上面的代码:
这段代码的区别是在多执行了一次System.gc(),结果如下:
null
null
======================
null
java.lang.ref.PhantomReference@10b30a7
多执行一次System.gc()之后,就正常加入到了ReferenceQueue队列中了,其原因就是“if
it declares a finalize() method itself, then its finalizer will have been run“,因为第一次执行GC的时候,F实例的状态为finalizable状态,即有finalize方法没有被执行。而第二次运行gc的时候,F实例的finalize方法已经执行完成,所以能正常加入ReferenceQueue。在第一段代码中,因为没有重载finalize的方法,java虚拟机会完成自动优化。其实这样做的目的是避免在finalize的方法中出现对象再生的情况。这个跟weakReference有着明显的区别,这一点也可以更可靠的监视一个对象是否被回收。
determined to not be resurrectable by any finalizer (if it declares a finalize() method itself, then its finalizer will have been run), and is reachable from the roots via one or more (uncleared) phantom reference objects. As soon as an object referenced by
a phantom reference object becomes phantom reachable, the garbage collector will enqueue it. The garbage collector will never clear a phantom reference. All phantom references must be explicitly cleared by the program.
这段话说明了phantom
reachable与strongly, softly, weakly reachable的区别,不好理解的话在“if
it declares a finalize() method itself, then its finalizer will have been run“。
public class E { public static void main(String[] args) { ReferenceQueue queue = new ReferenceQueue(); PhantomReference ref = new PhantomReference(new F(), queue); System.out.println(ref.get()); Object obj = null; obj = queue.poll(); System.out.println(obj); System.gc(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ref.get()); obj = queue.poll(); System.out.println(obj); } } class F{ }先看上面这个例子,运行结果如下:
null
null
null
java.lang.ref.PhantomReference@10b30a7
这个结果正常,符合对PhantomReference的文档说明,PhantomReference引用的对象是unreachable的,即使未被垃圾回收器回收,通过get方法返回的也是空。接下来修改一下上面的实例:
public class E { public static void main(String[] args) { ReferenceQueue queue = new ReferenceQueue(); PhantomReference ref = new PhantomReference(new F(), queue); System.out.println(ref.get()); Object obj = null; obj = queue.poll(); System.out.println(obj); System.gc(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(ref.get()); obj = queue.poll(); System.out.println(obj); } } class F{ @Override protected void finalize() throws Throwable { System.out.println("======================"); super.finalize(); } }运行的结果:
null
null
======================
null
null
上一段代码唯一的区别就是F类重载了finalize方法,重载之后通过gc回收后,却没有加入到ReferenceQueue之中。然后再稍微修改上面的代码:
public class E { public static void main(String[] args) { ReferenceQueue queue = new ReferenceQueue(); PhantomReference ref = new PhantomReference(new F(), queue); System.out.println(ref.get()); Object obj = null; obj = queue.poll(); System.out.println(obj); System.gc(); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.gc();//重新执行垃圾回收 System.out.println(ref.get()); obj = queue.poll(); System.out.println(obj); } } class F{ @Override protected void finalize() throws Throwable { System.out.println("======================"); super.finalize(); } }
这段代码的区别是在多执行了一次System.gc(),结果如下:
null
null
======================
null
java.lang.ref.PhantomReference@10b30a7
多执行一次System.gc()之后,就正常加入到了ReferenceQueue队列中了,其原因就是“if
it declares a finalize() method itself, then its finalizer will have been run“,因为第一次执行GC的时候,F实例的状态为finalizable状态,即有finalize方法没有被执行。而第二次运行gc的时候,F实例的finalize方法已经执行完成,所以能正常加入ReferenceQueue。在第一段代码中,因为没有重载finalize的方法,java虚拟机会完成自动优化。其实这样做的目的是避免在finalize的方法中出现对象再生的情况。这个跟weakReference有着明显的区别,这一点也可以更可靠的监视一个对象是否被回收。
相关文章推荐
- 深入理解StrongReference,SoftReference, WeakReference和PhantomReference
- PhantomReference的个人理解
- 深入理解java中的Soft references && Weak references && Phantom reference
- 深入理解java中的Soft references && Weak references && Phantom reference
- Java的StrongReference、WeakReference、SoftReference、PhantomReference的理解
- 正确理解ThreadLocal
- 如何正确理解PHP获取显示数据库数据函数
- 正确理解ThreadLocal
- java中的三个引用类 SoftReference, WeakReference 和 PhantomReference的区别
- 如何理解并正确使用MySql索引
- 不只是给面试加分 -- Java WeakReference的理解与使用
- TCP三次握手连接及seq和ack号的正确理解
- 【转】正确理解hibernate的inverse!
- (非常重要)如何正确理解PHP之include,include_once,require,require_once等包含作用域
- 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式
- [转]零基础学Qt 4编程实例之四:理解并正确使用名字空间
- 正确理解ThreadLocal
- effective stl 第28条:正确理解由reverse_iterator的base()成员函数所长生的iterator的用法
- 理解和正确使用Java中的断言(assert)
- java强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference),PhantomRefrence(虚引用)的区别