Java 在其他对象之前防止对象垃圾回收

Java 在其他对象之前防止对象垃圾回收,java,garbage-collection,finalization,Java,Garbage Collection,Finalization,我有一个弱引用数组,其中包含对其他对象的弱引用,如下所示: public class Foo{ WeakReference<WeakReference<Bar>[]> cache; } public class Bar{ private final WeakReference<Bar>[] ownerCache; } 公共类Foo{ WeakReference缓存; } 公共类酒吧{ 私有最终WeakReference[]所有者缓存; }

我有一个弱引用数组,其中包含对其他对象的弱引用,如下所示:

public class Foo{
    WeakReference<WeakReference<Bar>[]> cache;
}
public class Bar{
    private final WeakReference<Bar>[] ownerCache;
}
公共类Foo{
WeakReference缓存;
}
公共类酒吧{
私有最终WeakReference[]所有者缓存;
}
由于我现在不想讨论的原因,数组本身被弱引用。我想确保在可以从它访问任何Bar对象之前,它没有被垃圾收集。换句话说,它必须存在于内存中,只要存在可以从它访问的任何Bar对象。然后,如果不再存在Bar对象,那么如果数组也是垃圾收集的,我会更好。(从其他地方可以很强地访问Bar对象,也可能无法访问。)我是通过引用所有Bar对象内字段中的缓存数组来实现这一点的。如果该字段足以使数组强可访问,则不会对其进行垃圾收集。然而,我的代码从未实际使用过该字段,我无法将其公开。(我得到了“unused”警告。)我担心这类字段的存在会在编译时或运行时终止,或者它可能会得到我不知道的垃圾收集器的特殊处理


这是正确的解决方案吗?不管垃圾收集器或JVM实现如何,这个解决方案都能实现我想要的吗?如果没有,还有什么更好的方法呢?

以下是一些想法

如果您控制Bar类,并且每个实例仅由一个数组引用,则可以将Bar实例中的引用添加到该数组中。可访问的Bar实例将阻止收集阵列

或者,您可以:

  • 为对Bar实例的弱引用构造引用队列

    ReferenceQueue<Bar> m_refQueue = new ReferenceQueue<>();
    
    ReferenceQueue m_refQueue=new ReferenceQueue();
    
  • 用对该队列的引用构造每个WeakReference

    new WeakReference<Bar>( myBar, m_refQueue );
    
    newweakreference(myBar,m_refQueue);
    
  • 定期轮询该队列以查找可用的可收集实例,并将其从集合中删除

  • 您可以使集合本身成为一个可调整大小的数据结构,从而避免收集它的需要

    public class Foo {
       final @Nonnull List<WeakReference<Bar>> cache = new ArrayList<>();
    
       // Or you could use an IdentityHashSet from a third-party library.
    }
    
    公共类Foo{
    final@Nonnull List cache=new ArrayList();
    //或者,您可以使用第三方库中的IdentityHashSet。
    }
    
  • 编辑

    正如下面@Holger所建议的,如果不需要一个有序的引用列表,那么WeakReference集合可以是一个,用作一个集合。关键是弱引用;这些值可以为null。映射是一个可调整大小的数据结构,因此您可以简单地保存对映射的普通引用

        public class Foo {
           final @Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
              = new WeakHashMap<>();
    
    公共类Foo{
    最终@Nonnull WeakHashMap缓存
    =新WeakHashMap();
    
    如果对象的集合具有可观察的效果,则堆字段足以使对象保持活动状态,无论是否使用该字段。请注意,这种优化仅在引用位于堆栈上而不是存储在堆中时才允许。您可以添加
    @SuppressWarnings(“未使用”)
    。这非常有助于打开我的思路,让我了解其他可以实现同样目的的方法。我转而使用一个HashMap,该HashMap中的WeakReference值也存储了它们的键,因此我可以使用引用队列从映射中删除最终的条目。我不知道引用队列可以这样使用。@Gergely你知道已经有这样的方法了吗真的吗?我知道WeakHashMap,我确实考虑过了,但是我想要弱引用的值而不是键。用它作为一个弱集对我没什么好处,因为我需要以某种方式索引我的条目。基本上,我需要能够回答这个问题:“给定整数ID的条目还是内存中的。”非常频繁。我对ID没有任何控制权,只知道它们是由非盐计数器生成的。0,1,2,3,4。。。