Java 引用队列的含义
我试图理解classJava 引用队列的含义,java,garbage-collection,weak-references,phantom-reference,Java,Garbage Collection,Weak References,Phantom Reference,我试图理解classReferenceQueue 它是的可选构造函数参数 SoftReference 及 它也是PhantomReference的必需参数 根据我读到的信息,我可以写一些论文 a) 对于PhantomReference方法,get始终返回null (b) 对于幻影参考: 1.gc检测到可以从内存中删除对象 2.对放入引用队列的对象的引用 当我们从队列调用clear或link-to-reference时,因为无法访问而gc看到 3.finalize方法调用 4.可用内存 对于弱/
ReferenceQueue
它是的可选构造函数参数
SoftReference
及
它也是PhantomReference
的必需参数
根据我读到的信息,我可以写一些论文
a) 对于PhantomReference方法,get始终返回null
(b)
对于幻影参考:1.gc检测到可以从内存中删除对象
2.对放入引用队列的对象的引用
当我们从队列调用clear或link-to-reference时,因为无法访问而gc看到 3.finalize方法调用
4.可用内存
对于弱/软引用:
1.gc检测到可以从内存中删除对象
2.finalize方法调用
3.可用内存
4.对放入队列的对象的引用
XXXReference
构造函数PhantomReference
没有没有ReferenceQueue
的构造函数PhantomReference
的目的是成为常规定稿的更灵活的替代方案。但是,为了使其工作,必须将引用排入队列,以使最终完成替换代码工作。(无法处理未排队的PhantomReference
)
相比之下,SoftReference
和WeakReference
对象通常在不排队的情况下很有用
4) 让ReferenceQueue的get方法总是返回null的原因是什么
ReferenceQueue
API没有get()
方法,所以我猜您是在谈论PhantomReference
API。之所以有get()
方法是为了与超类兼容。将get()
定义为返回null
的原因如下:
为了确保可回收对象保持这种状态,可能无法检索幻像引用的referent:幻像引用的get方法始终返回null
(见附件。)
换句话说,这样做是为了使所指对象不可能“复活”
更新
事实上,所有Reference
类将在将Reference
排队之前清除referent。(实际上,GC本身直接执行此操作。)从ReferenceQueue
提取引用的应用程序代码不能使用get()
方法来标识(现在已删除!)引用对象。他们必须以另一种方式去做;e、 g.基于参考对象的标识
幻影引用的区别在于get()
方法总是返回null
。(所以javadoc中的解释……不令人信服。)
1) 何时可以将第二个参数传递给XXXReference构造函数
你想什么时候做就什么时候做。当引用被破坏时,只要需要处理它们,就应该这样做
2) 我能得到什么帮助
我不明白这个问题
3) 为什么PhantomReference没有无ReferenceQueue的构造函数
PhantomReference
的目的是成为常规定稿的更灵活的替代方案。但是,为了使其工作,必须将引用排入队列,以使最终完成替换代码工作。(无法处理未排队的PhantomReference
)
相比之下,SoftReference
和WeakReference
对象通常在不排队的情况下很有用
4) 让ReferenceQueue的get方法总是返回null的原因是什么
ReferenceQueue
API没有get()
方法,所以我猜您是在谈论PhantomReference
API。之所以有get()
方法是为了与超类兼容。将get()
定义为返回null
的原因如下:
为了确保可回收对象保持这种状态,可能无法检索幻像引用的referent:幻像引用的get方法始终返回null
(见附件。)
换句话说,这样做是为了使所指对象不可能“复活”
更新
事实上,所有Reference
类将在将Reference
排队之前清除referent。(实际上,GC本身直接执行此操作。)从ReferenceQueue
提取引用的应用程序代码不能使用get()
方法来标识(现在已删除!)引用对象。他们必须以另一种方式去做;e、 g.基于参考对象的标识
幻影引用的区别在于
get()
方法总是返回null
。(所以javadoc中的解释……不太令人信服。)也许,下面的程序有点帮助:
public class SimpleGCExample {
public static void main(String[] args) throws InterruptedException {
ReferenceQueue<Object> queue=new ReferenceQueue<>();
SimpleGCExample e = new SimpleGCExample();
Reference<Object> pRef=new PhantomReference<>(e, queue),
wRef=new WeakReference<>(e, queue);
e = null;
for(int count=0, collected=0; collected<2; ) {
Reference ref=queue.remove(100);
if(ref==null) {
System.gc();
count++;
}
else {
collected++;
System.out.println((ref==wRef? "weak": "phantom")
+" reference enqueued after "+count+" gc polls");
}
}
}
@Override
protected void finalize() throws Throwable {
System.out.println("finalizing the object in "+Thread.currentThread());
Thread.sleep(100);
System.out.println("done finalizing.");
}
}
或
在线程中终结对象[终结器,8,系统]
弱引用在1次gc轮询后排队
完成定稿。
幻象引用在2次gc轮询后排队
由于多线程,前两条消息的顺序有时会有所不同。有时,幻影引用报告在三次轮询后进入队列,这表明它花费的时间超过了指定的100毫秒
关键是
- 软引用和弱引用被清除
public class SimpleGCExample { public static void main(String[] args) throws InterruptedException { ReferenceQueue<Object> queue=new ReferenceQueue<>(); SimpleGCExample e = new SimpleGCExample(); Reference<Object> pRef=new PhantomReference<>(e, queue), wRef=new WeakReference<>(e, queue); e = null; for(int count=0, collected=0; collected<2; ) { Reference ref=queue.remove(100); if(ref==null) { System.gc(); count++; } else { collected++; System.out.println((ref==wRef? "weak": "phantom") +" reference enqueued after "+count+" gc polls"); } } } @Override protected void finalize() throws Throwable { System.out.println("finalizing the object in "+Thread.currentThread()); Thread.sleep(100); System.out.println("done finalizing."); } }