ReferenceQueue的含义 [英] Meaning of ReferenceQueue

查看:135
本文介绍了ReferenceQueue的含义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试着去理解类 ReferenceQueue



它是可选的构造函数参数

  SoftReference 

和 We b

$ b $ $ $ $













此外,它是 PhantomReference

的强制性参数。根据我读过的信息,我可以写一些thesises

对于Phantom引用,总是返回null b
$ b

b
$ b



1. gc检测该对象是否可以从内存中删除

2.引用该对象时引用Reference bueue

当我们调用clear或链接到队列引用,因为无法访问,gc看到
3.终止方法调用

4.空闲内存

用于弱/ strong>

1. gc检测到对象可以从内存中删除

2.敲定方法调用

3.释放内存

4.引用对象到队列中


  1. 何时可以将第二个参数传递给 XXXReference 构造函数?

  2. 我可以获得哪些帮助?

  3. 为什么 PhantomReference 没有 ReferenceQueue ?
  4. 没有构造函数
  5. 什么原因是否有ReferenceQuee的get方法总是返回null?


解决方案

也许,下面的程序有助于bit:

  public class SimpleGCExample {
public static void main(String [] args)throws InterruptedException {
ReferenceQueue< Object> queue = new ReferenceQueue<>();
SimpleGCExample e = new SimpleGCExample();
参考< Object> pRef = new PhantomReference<>(e,队列),
wRef = new WeakReference<>(e,队列);
e = null;
for(int count = 0,collected = 0; collect <2;){
Reference ref = queue.remove(100);
if(ref == null){
System.gc();
count ++;
}
else {
++ ++;
System.out.println((ref == wRef?weak:phantom)
+reference count enqueued after+ count +gc polls);



@Override
protected void finalize()throws Throwable {
System.out.println(finalizing the对象在+ Thread.currentThread());
Thread.sleep(100);
System.out.println(done finalizing。);






在我的系统上,它打印$ / $>

在1 gc polls
之后入队的弱引用在Thread [Finalizer,8,system]中完成对象
完成定稿。
phantom参考在2 gc民意测验后入场

在Thread [Finalizer,8,system]中完成对象
在1 gc polls
完成后排除了弱引用定稿。
phantom参考在2 gc民意调查后排队

前两条消息的顺序偶尔会有不同到多线程。有时,幻影参考被报告在三次民意调查后排队,表明它花费的时间超过了指定的100毫秒。



关键是




  • 软和弱引用被清除并且在开始完成之前或之后被排入队列

  • 幻影引用被排入之后 finalization,假设对象没有泄漏 finalize 方法,否则在对象再次无法访问后将它们排入队列。

  • < (非平凡的) finalize()方法的存在导致需要至少一个额外的垃圾收集周期来检测该对象不可达或虚幻可达再次


由于99%以上的所有对象都不需要终结,所以强烈建议所有JVM供应商检测 finalize()没有被覆盖或者是微不足道的,即一个空方法或一个单独的 super .finalize()调用。在这些情况下,终止步骤应该被忽略。通过删除上例中的 finalize()方法,您可以轻松地检查此优化是否发生在您的JVM中。然后打印

弱引用在1 gc polls
后排入队列phantom引用在1之后排入队列gc民意调查

因为两者都立即排队并以任意顺序检索,所以两个消息的顺序可能不同。但它们总是在一个gc循环后排队。



值得注意的是,幻影引用不会自动清除,这意味着它需要另一个垃圾收集循环,直到该对象的内存真的可以重用,所以上面的例子需要至少三个循环,其中包含非平凡的 finalize()方法,另外两个没有。 Java 9将会改变这种情况,自动清除幻影引用,所以在上面的例子中,最终需要两个周期,一个没有完成,直到内存真的可以被回收。嗯,准确地说,在这个简单的例子中,对象的内存永远不会被回收,因为程序在发生之前会终止。






<上面的代码还演示了Reference API的一个预期用例。我们可以使用它来检测对象在完全控制下的代码内的可访问性是否发生了变化,例如,使用主要方法中的循环。相反, finalize()可以在任意时间由另一个未指定的线程调用。该示例还显示,您可以从引用对象中获取信息,而不需要 get()方法。

实用应用程序通常使用参考类的子类向其添加更多信息。这是对 WeakHashMap.Entry 发生的事情,它扩展了 WeakReference 并记住哈希码和值。清理可以在正常的映射操作中完成,不需要任何线程同步。对于 finalize()方法,这是不可能的,除了地图实现不能推送 finalize()

这意味着比定稿更加灵活这个词。



WeakHashMap 演示了如何使用 get()方法。只要密钥没有被收集,它将被报告为在地图中,并且可以在遍历所有密钥或条目时被检索。



<$> c $ c> PhantomReference.get()方法已被覆盖,总是返​​回 null 以防止应用程序重新生成入队引用的引用。这是幻影参考不自动清除规则的直接结果。这个规则本身是有问题的,它的初衷在于黑暗。虽然规则即将在下一个Java版本中进行更改,但恐怕 get()将继续始终返回 null 向后兼容。


I try to understand class ReferenceQueue

It is optional constructor argument for

SoftReference

and

WeakReference

Also it is mandatory argument for PhantomReference.

According information I have read I can write some thesises

a)for PhantomReference method get always returns null

b) for Phantom references:
1. gc detect that object can be deleted from memory
2. reference to the object puted to the ReferenceQueue
when we invoke clear or link to reference from queue becaom unreachable and gc see that 3. finalize methods invokes
4. free memory
for weak/soft references:
1. gc detect that object can be deleted from memory
2. finalize methods invokes
3. free memory
4. reference to the object puted to the queue

  1. When can I pass second argument to XXXReference constructor?
  2. Which help I can get?
  3. Why PhantomReference has not constructor without ReferenceQueue ?
  4. What the reason to have ReferenceQuee which get methods returns null always?

解决方案

Maybe, the following program helps a bit:

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.");
    }
}

On my system, it prints

weak reference enqueued after 1 gc polls
finalizing the object in Thread[Finalizer,8,system]
done finalizing.
phantom reference enqueued after 2 gc polls

or

finalizing the object in Thread[Finalizer,8,system]
weak reference enqueued after 1 gc polls
done finalizing.
phantom reference enqueued after 2 gc polls

The order of the first two messages occasionally differs due to the multi-threading. And sometimes, the phantom reference is reported to be enqueued after three polls, indicating that it took more than the specified 100 milliseconds.

The key point is

  • soft and weak references are cleared and enqueued before or right when starting finalization
  • phantom references are enqueued after finalization, assuming that the object has not leaked the finalize method, otherwise they are enqueued after the object has become unreachable again
  • the presence of a (non-trivial) finalize() method causes the need of at least one additional garbage collecting cycle to detect that the object is unreachable or phantom reachable again

Since more than 99% of all objects don’t need finalization, all JVM vendors are strongly encouraged to detect when finalize() has not been overridden or is "trivial", i.e. an empty method or a sole super.finalize() call. In these cases, the finalization step should be elided. You can easily check that this optimization happens in your JVM, by removing the finalize() method in the above example. Then it prints

weak reference enqueued after 1 gc polls
phantom reference enqueued after 1 gc polls

Since both are enqueued at once and retrieved in an arbitrary order, the order of the two messages may differ. But they are always both enqueued after one gc cycle.

It’s worth noting that the fact, that phantom references are not automatically cleared, implies that it takes another garbage collection cycle until the object’s memory really can be reused, so the above example requires at least three cycles with the non-trivial finalize() method and two without. Java 9 is going to change that, clearing phantom references automatically, so in the above example it will take two cycles with finalization and one without until the memory really can be reclaimed. Well, to be precise, in this simple example the object’s memory will never be reclaimed as the program terminates before that can happen.


The code above also demonstrates one of the intended use cases of the Reference API. We can use it to detect when an object’s reachability changed within code under our full control, e.g. using a loop within the main method. In contrast, finalize() may be called by a different, unspecified thread at an arbitrary time. The example also shows that you can draw information from the reference object without needing the get() method.

Practical applications often use subclasses of the reference classes to add more information to them. This is what happens with WeakHashMap.Entry which extends WeakReference and remembers the hash code and value. The cleanup can be done within the normal map operations, not needing any thread synchronization. This would not be possible with a finalize() method, besides the fact that the map implementation can’t push a finalize() method into the class of the keys.

This is meant with the "more flexible than finalization" term.

The WeakHashMap demonstrates how the get() method can be useful. As long as the key hasn’t been collected, it will be reported as being in the map and can be retrieved when iterating over all keys or entries.

The PhantomReference.get() method has been overwritten to always return null to prevent that an application can resurrect the referent of an enqueued reference. This is a direct consequence of the "phantom references are not automatically cleared" rule. That rule itself is questionable and it’s original intention lies in the dark. While the rule is about to be changed in the next Java version, I’m afraid that get() will continue to always return null to be backwards compatible.

这篇关于ReferenceQueue的含义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆