在其他对象之前防止对象垃圾回收
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 实例将阻止收集数组。
或者,您可以:
为Bar实例的弱引用构造一个引用队列。
ReferenceQueue<Bar> m_refQueue = new ReferenceQueue<>();
使用对该队列的引用构造每个 WeakReference。
new WeakReference<Bar>( 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.
}
编辑
正如下面@Holger 所建议的,如果不需要有序的引用列表,您的 WeakReference 集合可以是 java.util.WeakHashMap,用作集合。键是弱引用;值可以为空。地图是一个可调整大小的数据结构,因此您可以简单地保存对地图的普通引用。
public class Foo {
final @Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
= new WeakHashMap<>();
我有一个弱引用数组,包含对更多对象的弱引用,如下所示:
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 实例将阻止收集数组。
或者,您可以:
为Bar实例的弱引用构造一个引用队列。
ReferenceQueue<Bar> m_refQueue = new ReferenceQueue<>();
使用对该队列的引用构造每个 WeakReference。
new WeakReference<Bar>( 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. }
编辑
正如下面@Holger 所建议的,如果不需要有序的引用列表,您的 WeakReference 集合可以是 java.util.WeakHashMap,用作集合。键是弱引用;值可以为空。地图是一个可调整大小的数据结构,因此您可以简单地保存对地图的普通引用。
public class Foo {
final @Nonnull WeakHashMap<WeakReference<Bar>,Object> cache
= new WeakHashMap<>();