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

Prevent object garbage collection before other objects

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

public class Foo{
    WeakReference<WeakReference<Bar>[]> cache;
}
public class Bar{
    private final WeakReference<Bar>[] ownerCache;
}

由于我现在不会讨论的原因,数组本身是弱引用的。我想确保在从它可访问的任何 Bar 对象之前,它不会被垃圾收集。换句话说,只要存在可以从它访问的任何 Bar 对象,它就必须存在于内存中。然后,如果不再存在 Bar 对象,如果数组也被垃圾收集,我会更好。 (Bar 对象可能会或可能不会从其他地方被强访问。)我通过引用所有 Bar 对象内的字段中的缓存数组来做到这一点。如果该字段足以使数组强可达,则不会对其进行垃圾回收。但是,我的代码从未真正使用过该字段,我无法做到 public。 (我收到了 "unused" 警告。)我担心这个字段的存在会在编译时或 运行 时终止,或者它可能会从我所在的垃圾收集器中得到特殊处理不知道。

这是正确的解决方案吗?无论垃圾收集器或 JVM 实现如何,此解决方案是否实现了我想要的?如果没有,什么是更好的方法?

这里有一些想法。

如果您控制 Bar class,并且每个实例只被一个数组引用,您可以将 Bar 实例的引用添加到数组。 Reachable Bar 实例将阻止收集数组。

或者,您可以:

  1. 为Bar实例的弱引用构造一个引用队列。

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

    new WeakReference<Bar>( myBar, m_refQueue );
    
  3. 定期轮询该队列以查找可用的可收集实例,并将它们从您的集合中移除。

  4. 您可以使集合本身成为可调整大小的数据结构,避免收集它的需要。

    public class Foo {
       final @Nonnull List<WeakReference<Bar>> cache = new ArrayList<>();
    
       // Or you could use an IdentityHashSet from a third-party library.
    }
    

编辑

正如下面@Holger 所建议的,如果不需要有序的引用列表,您的 WeakReference 集合可以是 java.util.WeakHashMap,用作集合。键是弱引用;值可以为空。地图是一个可调整大小的数据结构,因此您可以简单地保存对地图的普通引用。

    public class Foo {
       final @Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
          = new WeakHashMap<>();