【发布时间】:2016-05-05 20:20:06
【问题描述】:
假设我有三个对象,A、B 和 C。
A 以软引用引用B。B 以强引用引用A。B 也以强引用引用C。C 也指具有强引用的B。C 也指具有强引用的A。
让我们假设没有对B 或C 的外部引用。如果我们想象这样一种情况,垃圾收集器决定如果可以的话,它会尝试释放软引用指向的内存,B 和 C 是否会被释放,而留下A?或者在从B 和C 到A 的反向链接以某种方式阻止垃圾收集发生时,是否会发生某种循环依赖?我的理解是 GC 应该在 OutOfMemory 被抛出之前收集软引用。
这是一个高度内存密集型应用程序,它模拟了一个非常大的层次结构,因此我希望 GC 丢弃层次结构的“分支”,只要没有对它们的强引用。我可以在必要时重新生成分支,但这在计算上很昂贵,因此我使用软引用实现了缓存。我的一般策略是让软引用指向下游(即树的子节点)和指向父节点的强引用。
【问题讨论】:
-
是的,B 和 C 可以进行 GC,但垃圾收集器在选择对 GC 的软引用方面非常愚蠢。
-
没关系,只要它最终会收集。要存储整个真实的数据模型,大约需要 80GB 的内存。缓存机制似乎在起作用,但我想确定一下。
-
我建议你有一个完全是强引用的小缓存,这会溢出到软/弱引用的缓存中。这样,当你 GC 和系统必须赶上它时,它也不会完全丢失它的缓存(即你会发现几乎所有的软引用都被清理了)
-
@PeterLawrey 考虑到应用程序,要跟踪该池中实际使用的硬引用将非常困难。在某个地方,我必须拥有某种地图,并且根据我对这个池的请求数量(1 亿+),查找时间会杀死我。但是,所有软引用不太可能一次全部被 GC,因为如果我对一个对象有一个强引用,那么层次结构树的该部分是可以访问的。
-
@bss36504 并非所有引用都会被清理,但可能是 99%。您不需要跟踪这一点,您可以使用具有固定大小和强引用的简单 LRU,它会溢出到带有软引用的缓存中。这可确保始终保留最近使用的 N 个条目缓存,并为您提供一定程度的控制。
标签: java