【问题标题】:Java Soft ReferencesJava 软引用
【发布时间】:2016-05-05 20:20:06
【问题描述】:

假设我有三个对象,A、B 和 C。

A 以软引用引用B
B 以强引用引用A
B 也以强引用引用CC 也指具有强引用的B
C 也指具有强引用的A

让我们假设没有对BC 的外部引用。如果我们想象这样一种情况,垃圾收集器决定如果可以的话,它会尝试释放软引用指向的内存,BC 是否会被释放,而留下A?或者在从BCA 的反向链接以某种方式阻止垃圾收集发生时,是否会发生某种循环依赖?我的理解是 GC 应该在 OutOfMemory 被抛出之前收集软引用。

这是一个高度内存密集型应用程序,它模拟了一个非常大的层次结构,因此我希望 GC 丢弃层次结构的“分支”,只要没有对它们的强引用。我可以在必要时重新生成分支,但这在计算上很昂贵,因此我使用软引用实现了缓存。我的一般策略是让软引用指向下游(即树的子节点)和指向父节点的强引用。

【问题讨论】:

  • 是的,B 和 C 可以进行 GC,但垃圾收集器在选择对 GC 的软引用方面非常愚蠢。
  • 没关系,只要它最终会收集。要存储整个真实的数据模型,大约需要 80GB 的内存。缓存机制似乎在起作用,但我想确定一下。
  • 我建议你有一个完全是强引用的小缓存,这会溢出到软/弱引用的缓存中。这样,当你 GC 和系统必须赶上它时,它也不会完全丢失它的缓存(即你会发现几乎所有的软引用都被清理了)
  • @PeterLawrey 考虑到应用程序,要跟踪该池中实际使用的硬引用将非常困难。在某个地方,我必须拥有某种地图,并且根据我对这个池的请求数量(1 亿+),查找时间会杀死我。但是,所有软引用不太可能一次全部被 GC,因为如果我对一个对象有一个强引用,那么层次结构树的该部分是可以访问的。
  • @bss36504 并非所有引用都会被清理,但可能是 99%。您不需要跟踪这一点,您可以使用具有固定大小和强引用的简单 LRU,它会溢出到带有软引用的缓存中。这可确保始终保留最近使用的 N 个条目缓存,并为您提供一定程度的控制。

标签: java


【解决方案1】:

我们假设存在对对象A 的外部强引用。 (即一些“根”对象指向A。)

通过definition,对象B 是软可访问的,因为没有强引用链可以到达B,但是有一个链由强引用和软引用组成,可以到达B。因此,JVM 可以自行决定对B 进行垃圾回收。

同样,对象C不是强可达而是软可达,因此它也可以像B一样被垃圾回收。

由于定义了从根到达对象,BC 形成一个循环这一事实没有任何区别。 Java 使用完全通用的跟踪垃圾收集(标记和清除或复制),它不受基于引用计数的垃圾收集所遭受的引用周期的影响。

【讨论】:

    【解决方案2】:

    指向树后面的硬引用不会阻止 B 和 C 被收集。

    【讨论】:

      猜你喜欢
      • 2010-10-26
      • 1970-01-01
      • 1970-01-01
      • 2012-01-17
      • 2010-10-02
      • 2011-01-26
      • 1970-01-01
      • 2012-04-06
      • 2015-10-19
      相关资源
      最近更新 更多