1

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

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

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

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

4

1 回答 1

2

这里有几个想法。

如果您控制 Bar 类,并且每个实例被不超过一个数组引用,则可以将 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<>();
于 2020-02-28T20:43:04.407 回答