- 浏览: 796875 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (651)
- Java (39)
- Java 初学者小问题 (66)
- 设计模式 (7)
- 项目管理 (3)
- 数据库 (1)
- 算法 (2)
- Java practices (6)
- Effective Java2读书笔记 (78)
- Linux (2)
- programming ruby 读书笔记 (5)
- Core Java Ninth Edition Volume I 读书笔记 (15)
- Pro Git 读书笔记 (12)
- Git (3)
- Maven in Action 读书笔记 (20)
- Web (12)
- 非技术类书籍 (11)
- 电影 (40)
- Web Cache (1)
- jquery (0)
- 历史 (4)
- Dive Into HTML5 读书笔记 (13)
- 三国演义小学毕业考 (79)
- 高效能人士的7个习惯 读书笔记 (12)
- Java Performance 读书笔记 (3)
- Protocol Buffer 学习笔记 (6)
- Mongo DB 学习笔记 (7)
- Morphia 学习笔记 (7)
- Algorithms -- Princeton 学习笔记 (13)
- String研究 (10)
- Hadoop: The Definitive Guide 读书笔记 (3)
- Java与模式读书笔记 (5)
- Date研究 (3)
- The Roman Empire 听课笔记 (4)
- Algorithms -- Standford 学习笔记 (16)
- Core Java Ninth Edition Volume II 读书笔记 (9)
- Thinking in Java 4th Edition 读书笔记 (21)
- Node : Up and Running 学习笔记 (5)
- Eloquent Javascript (8)
- Smashing Node.js 读书笔记 (1)
- Algorithms II -- Standford 学习笔记 (19)
- Algorithm II -- Princeton 学习笔记 (14)
- 网络安全 (2)
- Javascript (4)
- 正则表达式 (1)
- JAVA 7/8 (15)
- JVM (10)
- NodeJS (1)
- 鸟哥的linux私房菜读书笔记 (14)
- Web Service (1)
- The art of programming (9)
- Introduction to Algorithm 读书笔记 (4)
- Java 源码阅读 (0)
- Spring in Action 读书笔记 (2)
- Java Network Programming 读书笔记 (2)
最新评论
-
心存高远:
谢谢作者分享,刚好看到这里不太明白,现在茅塞顿开。不过runt ...
关于 Maven的传递依赖的理解 -
sxlkk:
851228082 写道甚至在某次技术会议现场遇到《Maven ...
关于 Maven的传递依赖的理解 -
851228082:
851228082 写道a----compile----b-- ...
第五章 坐标和依赖 -
851228082:
a----compile----b-----provided- ...
第五章 坐标和依赖 -
851228082:
甚至在某次技术会议现场遇到《Maven in action》的 ...
关于 Maven的传递依赖的理解
阅读了 Guidelines for using the Java 2 reference classes 与 Understanding Weak References 之后,发现两篇文章关于 WeakReference 和 PhantomReference 何时被加入到 ReferenceQueue有些出入。也就是说到底是在引用的对象没有强引用时还是在引用的对象真正被回收时。于是写了如下程序进行验证:
package mypackage; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; class TestObj { //定义三种Reference用于保存指向本对象的Reference,从而在finalize中检验他们的get()值 private SoftReference sr = null; private WeakReference wr = null; private PhantomReference pr = null; //定义ReferenceQueue用于在finalize中检验指向本对象的reference是否被加入了这个Queue private static ReferenceQueue rq = null; public static void setQueue(ReferenceQueue referenceQueue) { rq = referenceQueue; } public void setSr(SoftReference sr) { this.sr = sr; } public void setWr(WeakReference wr) { this.wr = wr; } public void setPr(PhantomReference pr) { this.pr = pr; } public void finalize() { //检验指向本对象的Reference的get()值 if (null != sr) System.out.println("Soft Reference refers to " + sr.get() + " in finalize()."); if (null != wr) System.out.println("Weak Reference refers to " + wr.get() + " in finalize()."); if (null != pr) System.out.println("Phantom Reference refers to " + pr.get() + " in finalize()."); //验证是不是在对象finalize()的时候他的soft reference已经被加入至Queue中 Reference r = rq.poll(); while (null != r) { System.out.println(r.getClass().getName() + " is added in the queue in finalize()."); r = rq.poll(); } } } public class Test { public static void main(String[] args) { { //用于传给三种Reference的强引用 TestObj softObj = new TestObj(); TestObj weakObj = new TestObj(); TestObj phantomObj = new TestObj(); ReferenceQueue rq = new ReferenceQueue(); //三种Reference指向三个不同的对象 SoftReference sr = new SoftReference(softObj, rq); WeakReference wr = new WeakReference(weakObj, rq); PhantomReference pr = new PhantomReference(phantomObj, rq); //将Reference传回给对应的对象 softObj.setSr(sr); weakObj.setWr(wr); phantomObj.setPr(pr); //将ReferenceQueue传回给对象类 TestObj.setQueue(rq); //删除强引用 softObj = null; weakObj = null; phantomObj = null; System.gc(); Reference r = null; // 为了确保对象被GC回收 //****************************************** while (null == r) { System.gc(); r = rq.poll(); } //****************************************** while (null != r) { System.out.println(r.getClass().getName() + " is added in the queue out of finalize()."); r = rq.poll(); } } } }
但发现程序输出的结果是:
Phantom Reference refers to null in finalize(). Weak Reference refers to null in finalize(). Soft Reference refers to null in finalize().
这就有点让我纳闷了,到底是这些Reference没被加入Queue中呢还是内存中的对象没了被真正回收呢? 以/********包围起来的语句是我后来加上去的,是为了确保对象确实被回收,但发现这样的话程序就死循环了。
请高手解疑:)
评论
5 楼
leonzhx
2010-10-01
JDK 1.6的ReferenceQueue.enqueue
boolean enqueue (Reference reference) { if (reference instanceof sun.misc.Cleaner) { reference.dequeue(); ((sun.misc.Cleaner)reference).clean(); return true; } synchronized(this) { if(!empty && head == tail) { /* Queue is full - grow */ int newQueueSize = (int)(references.length * 1.10); Reference newQueue[] = new Reference[newQueueSize]; System.arraycopy(references, head, newQueue, 0, references.length - head); if(tail > 0) { System.arraycopy(references, 0, newQueue, references.length - head, tail); } head = 0; tail = references.length; references = newQueue; } references[tail++] = reference; if(tail == references.length) { tail = 0; } empty = false; notifyAll(); } return true; }
4 楼
leonzhx
2010-10-01
你说的ReferenceQueue贴出来是什么意思?
现在程序出的只是各种Reference的get()方法的输出。程序执行时就在
死循环了,说明ReferenceQueue里一直没东西。
现在程序出的只是各种Reference的get()方法的输出。程序执行时就在
引用
while (null == r)
{
System.gc();
r = rq.poll();
}
{
System.gc();
r = rq.poll();
}
死循环了,说明ReferenceQueue里一直没东西。
3 楼
mercyblitz
2010-10-01
leonzhx 写道
谢谢mercyblitz的指教。我更新了一下代码并加了一些注释。
首先,你贴的是ReferenceQueue的enqueue的代码吧?我这里JDK1.6好像不是长这样的。。。
其次,就是因为System.gc()靠不住,所以我加了/*********包起来的那段,但程序还是死循环。。。
首先,你贴的是ReferenceQueue的enqueue的代码吧?我这里JDK1.6好像不是长这样的。。。
其次,就是因为System.gc()靠不住,所以我加了/*********包起来的那段,但程序还是死循环。。。
没有错,你的ReferenceQueue贴出来呢!
2 楼
leonzhx
2010-10-01
谢谢mercyblitz的指教。我更新了一下代码并加了一些注释。
首先,你贴的是ReferenceQueue的enqueue的代码吧?我这里JDK1.6好像不是长这样的。。。
其次,就是因为System.gc()靠不住,所以我加了/*********包起来的那段,但程序还是死循环。。。
首先,你贴的是ReferenceQueue的enqueue的代码吧?我这里JDK1.6好像不是长这样的。。。
其次,就是因为System.gc()靠不住,所以我加了/*********包起来的那段,但程序还是死循环。。。
1 楼
mercyblitz
2010-10-01
代码没有怎么看明白!
一般而言,Strong、Soft、Weak和Phantom描述的是对象可达性,只有完全不可达时,对象才会真正的回收。
对象回收至少经过两个周期,前finalize期,可达性从Strong->Soft->Weak。
下个周期-finalize期,这个时候对象编程了,final reference(finalize可达性),在JDK中提供一个非public的类 - java.lang.ref.FinalReference。
SUN JDK源码中有提示:
对象被finalized之后,对象的可达性为finalize。
而Phantom在finalize之后,这就是为什么引用对象总是返回null。
因此,SUN JDK里有5个可达性,按照强弱排列:Strong、Soft、Weak、Finalize和Phantom。
注意除了Phantom以外,ReferenceQueue都会返回被入队的引用。
另外,System.gc(); 是靠不住的。所以,多次运行结果会不多。
一般而言,Strong、Soft、Weak和Phantom描述的是对象可达性,只有完全不可达时,对象才会真正的回收。
对象回收至少经过两个周期,前finalize期,可达性从Strong->Soft->Weak。
下个周期-finalize期,这个时候对象编程了,final reference(finalize可达性),在JDK中提供一个非public的类 - java.lang.ref.FinalReference。
SUN JDK源码中有提示:
boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */ synchronized (r) { if (r.queue == ENQUEUED) return false; synchronized (lock) { r.queue = ENQUEUED; r.next = (head == null) ? r : head; head = r; queueLength++; if (r instanceof FinalReference) { // sun.misc.VM.addFinalRefCount(1); //添加final reference 计数 } lock.notifyAll(); return true; } } }
对象被finalized之后,对象的可达性为finalize。
而Phantom在finalize之后,这就是为什么引用对象总是返回null。
因此,SUN JDK里有5个可达性,按照强弱排列:Strong、Soft、Weak、Finalize和Phantom。
注意除了Phantom以外,ReferenceQueue都会返回被入队的引用。
另外,System.gc(); 是靠不住的。所以,多次运行结果会不多。
发表评论
文章已被作者锁定,不允许评论。
-
Zz The java.lang.LinkageError: loader constraint violation" demystified
2014-05-13 19:24 1520http://frankkieviet.blogspot.c ... -
zz Java NIO 系列教程
2014-05-09 22:38 1165http://www.iteye.com/magazines ... -
Zz Java NIO Tutorial
2014-05-09 22:34 1786http://tutorials.jenkov.com/ja ... -
Zz Spring IOC 好处和劣势
2014-03-28 18:06 1074IoC是什么? Inversion of Contro ... -
Zz ConcurrentHashMap源码解析
2014-03-16 17:29 668ConcurrentHashMap是Java 5中支持高并发 ... -
Zz Java多线程之ConcurrentHashMap深入分析
2014-03-16 14:50 1182一、Map体系 Hashtable是JDK ... -
Zz ConcurrentHashMap原理分析
2014-03-16 14:03 1127集合是编程中最常用的数据结构。而谈到并发,几乎总是离不开集合 ... -
Zz Java并发编程之ConcurrentHashMap
2014-03-16 13:40 2068ConcurrentHashMap Concurrent ... -
关于ConcurrentHashMap 中位移的问题
2014-03-16 14:33 1262拜读了GoldenDoc的大作:《Java并发编程之Con ... -
ConcurrentHashMap 详解
2014-03-15 21:19 01. ConcurrentHashMap 可以做到读取数 ... -
Why java Arrays use two different sort algorithms for different types?
2014-02-25 22:09 1304Java 7 uses Dual-Pivot Quicks ... -
深入探讨 java.lang.ref 包
2014-02-25 19:58 1093回顾了一下三年多前写的文章https://www.i ... -
Zz Java 中使用内存映射文件需要考虑的 10 个问题
2014-02-09 17:18 946java中的内存映射IO和内存映射文件是什么? 内存 ... -
Zz 10 Things to Know about Memory Mapped File in Java
2014-02-09 17:16 632What is Memory Mapped File ... -
Zz Direct vs non-direct ByteBuffer
2014-02-08 12:46 850先解释一下两者的区 ... -
Zz direct buffer VS non-direct buffer
2014-02-08 10:55 869在java NIO中,有两种不同的buffer:direct ... -
Java Generics 小结
2013-03-07 14:12 01. 泛型类型或泛型类 ... -
关于 Java正则表达式中的Possessive数量修饰词的理解
2013-02-26 21:14 1285正则表达式对于数量限定符如 ?, + , *, {n, m ... -
Run Application in debug mode
2013-01-23 13:59 1312Q: I use the Eclipse IDE to de ... -
一个 Dynamic Proxy 的例子
2012-11-22 11:18 1233最近翻出了两年前老吴让我写的一个MockFacotry , ...
相关推荐
在垃圾回收器对弱引用对象进行回收的时机。弱引用所指向的对象,无论内存状况如何,只要没有其他强引用存在,垃圾回收器在下一次执行GC时就会回收它,而不会等待内存压力达到某个阈值。弱引用通常用于创建临时性或者...
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 三、弱引用(WeakReference) 弱引用与软引用的区别...
软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。 弱引用(WeakReference)弱引用与软引用的区别在于:只...
它还可以与引用队列(ReferenceQueue)联合使用,一旦被引用的对象被回收,软引用本身会被加入到引用队列中。 弱引用(WeakReference)与软引用类似,但具有更短的生命周期。当垃圾回收器扫描内存区域时,不论当前...
软引用通常与`ReferenceQueue`配合使用,当对象被回收时,软引用会被加入到队列中。例如: ```java SoftReference<String> softRef = new SoftReference(new String("hello"), referenceQueue); ``` 3. **弱引用...
这些引用类型通过`java.lang.ref`包中的`SoftReference`、`WeakReference`和`PhantomReference`类实现,而`ReferenceQueue`类用于与这三种引用类型一起工作,记录引用对象被回收的信息。 以下是一个简单的例子展示...
- 示例:`PhantomReference<String> phantomRef = new PhantomReference(new String("PhantomReference Test"), new ReferenceQueue());` 理解这四种引用类型有助于开发者在设计和实现复杂系统时,更好地控制对象...
PhantomReference<String> phantomRef = new PhantomReference(str, queue); if (queue.poll() == null) { System.out.println("phantom reference is still valid."); } else { System.out.println("phantom ...
// 通过ReferenceQueue检查虚引用是否被加入队列 System.out.println(queue.poll()); // 输出 "abc" 的虚引用 } } ``` #### 六、总结 通过对软引用、弱引用和虚引用的介绍与示例代码,我们可以看到这三种引用...
当垃圾回收器准备回收一个对象时,如果发现该对象有虚引用,那么在回收对象之前,会将这个虚引用加入到与之关联的引用队列中。这样,开发者可以通过检查引用队列来确定对象是否已经被垃圾回收。 示例代码: ```java...
软引用会与引用队列(ReferenceQueue)配合使用,当软引用的对象被回收时,会被加入到引用队列。 3. **弱引用(WeakReference)**: 相比于软引用,弱引用的对象拥有更短的生命周期。在垃圾回收器扫描时,无论内存...
- 示例:`PhantomReference<String> phantomRef = new PhantomReference(new String("Hello"), new ReferenceQueue());` 这些引用类型的使用需要根据具体需求来选择。例如,软引用常用于缓存策略,以保持一定数量...
3. 使用虚引用(PhantomReference): 虚引用是最弱的一种引用类型,它不保证在任何时候都能获取到被引用的对象,只能在对象被回收后通过队列得知。虚引用主要用于跟踪对象被回收的状态,而不是延缓对象的回收。 4....
- **例子**:` PhantomReference<Object> phantomRef = new PhantomReference(new Object(), new ReferenceQueue());` - **特点**:虚引用主要用来跟踪对象被垃圾收集的状态,通常不用于内存管理。 了解和正确...
PhantomReference<String> pr = new PhantomReference(new String("hello"), new ReferenceQueue()); ``` 通过理解这四种引用,开发者可以在设计程序时更好地控制内存使用,避免内存泄漏,并在必要时优雅地处理...
当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象之前,把这个虚引用加入到与之关联的队列中。程序可以通过检查这个队列,获取到虚引用的信息,并采取相应的行动。 #### 六、总结 综上所述,...
1. 创建引用子类的实例,如`SoftReference`, `WeakReference`, 或 `PhantomReference`。 2. 将引用实例与目标对象关联。 3. 使用`get()`方法检查引用是否仍然有效。对于软引用和弱引用,如果对象被回收,`get()`将...
- 使用`ReferenceQueue`可以监控引用对象的状态变化,特别是对于`WeakReference`和`PhantomReference`。 - 避免过度依赖`SoftReference`作为缓存策略,因为它可能导致程序在内存紧张时不稳定。 - `PhantomReference`...
- 示例:`PhantomReference<Counter> phantom = new PhantomReference(new Counter(), new ReferenceQueue());` 即使对象仅被虚引用指向,也会立即被回收,但可以在对象被回收前通过队列获取通知。 **应用场景:**...