【问题标题】:Is there a way to FORCE weak and/or soft referenced objects to be GC'd in Java?有没有办法强制弱和/或软引用的对象在 Java 中被 GC?
【发布时间】:2011-10-21 12:58:47
【问题描述】:

这是我的用例。我们正在尝试缩小应用程序中潜在的内存泄漏,并且我们正在使用内存分析工具对堆进行快照,以便我们可以查找对象实例和引用。 (如果有帮助,我们正在使用 YourKit。)

此应用程序广泛使用动态代理和 CGLIB 代理,最终在 WeakHashMaps 中存储了大量对类和类加载器的引用。

在我们的测试用例运行之后,我们希望对对象 X 及其类加载器的所有硬引用都消失了,但是由于最终测试用例中涉及到许多代理,我们留下了许多弱/软引用。 (我只能找到 WeakHashMap 引用,但是 YourKit 将弱引用和软引用都包装到摘要中的一个行项中,所以我不能确定我没有在某处遗漏软引用。)

即使在从 JVM 请求完整的 GC 之后也是如此。 (在服务器模式下使用sun 1.6.0_23 JDK。)

似乎好像 JVM 承认这些对象只有弱/软引用,但我不能强迫它 GC 这些东西是 100% 确定的。 (所以,我希望它完全从堆中消失,并且它对 permgen 的类加载器使用也消失了。)

有人知道一种配置和/或强制 JVM 处理仅软/弱引用的对象的方法吗?

【问题讨论】:

  • 您是否偶然将您的对象注册到全球事件中?也许一个静态字段(或另一个线程对象或其他东西)对它们有引用......
  • 好问题 - 已经对此进行了调查,YourKit 提供了足够的信息来快速找到这类事情。虽然我仍在调查,但到目前为止,我已经将其范围缩小到(我认为)Spring 的 AOP 在使用 RegexpMethodPointcutAdvisor 代理类/方法时发起的一些行为。然而,这只是这个顾问的一个特例(到目前为止)——我们在许多似乎不会产生这个问题的地方使用它。仍在努力确定一个案例的独特之处......当我有更多时会回复。
  • 好的,这里是更新。我相信我已经为我的特定问题找到了确凿的证据。我们的应用程序中使用的代理之一在需要时从缓存中延迟加载其实现,以确保操作始终发生在最近缓存的对象上。如果缓存中没有对象,则缓存已配置为实例化和初始化对象。代理是一个相当愚蠢的代理,对于任何方法调用,它都会向缓存请求对象,然后调用对象上的方法。评论有字符限制,请继续阅读...
  • ...所以,在某些情况下,对象尚未缓存,但代理已存在。因此,当代理最终确定时,它将加载有问题的对象并将其存储在缓存中。虽然我没有追踪所有的依赖路径,但不知何故,这导致垃圾收集器决定不收集这些弱引用,然后级联到对类加载器的所有弱引用没有被收集。这意味着它创建了对相关类加载器的强引用,但如果是这样,我正在使用的工具(YourKit 和 jmap/jhat)不会向我显示。

标签: java reference garbage-collection weak-references soft-references


【解决方案1】:

调用 GC 应该始终释放所有弱可达对象(假设调用 System.gc 发出的“请求”实际上已被授予)。如果弱引用没有被 GC 清除,这意味着对象至少是软可访问的。

清除软引用比较棘手,因为这取决于 JVM 的判断。保证清除软可达对象的唯一方法是引发OutOfMemoryError 被抛出。这个技巧在this discussion 中得到了演示。

【讨论】:

  • System.gc 不只是一个提示吗?因此,这不是“否”问题的答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-28
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 2011-10-01
相关资源
最近更新 更多