另一个强制Java垃圾收集问题(带*我认为*一个合理的用例)

时间:2011-02-18 09:01:27

标签: java garbage-collection

我有一个数据生成器,它生成许多不同消费者使用的数据(我们称之为Cs)。每个C都有自己感兴趣的数据集。数据生成器对Cs的引用很弱,因此可以通知他们更新。

每个C也被许多独立组件使用,因此没有一个组件可以分辨何时不再需要C,所以我们必须将它留给JVM以确定何时C是GC能够的。

此处的目标是在C变得过时时收到通知,因此数据生产者可以关闭仅对未使用的C感兴趣的数据。

正如我前面提到的,数据生成器总是对Cs的引用很弱,所以当C是GC时很容易做到。但是,我注意到Cs通常会在VM最终GC-ed之前长时间停留在VM中,而这一切,数据生产者正在产生它应该需要的大量数据。

有没有办法强制GC使用未使用过的Cs?我希望是的,但是我期待一个No,所以作为一个后续问题,是否有人对我如何(重新)设计这个以使其更好/更有效地工作有一个很好的建议?

谢谢!

下面的一些答案提出了很多好处 - 尤其是强制用户C订阅和取消订阅的建议。这很难,因为:

C只是接口I的一种可能实现(没有此订阅要求),这是用户真正使用的。 C实现是在运行时注入的,因此我们不能强制用户遵守C特定的要求。 (哎哟?)

5 个答案:

答案 0 :(得分:2)

使用C的组件可以在他们感兴趣并且不再感兴趣时通知。

如果至少有一个感兴趣的组件,请启用订阅。 (此处不会出现此情况),当最后一个组件取消订阅时,请关闭数据。

Set<C> components = ...

public void subscribesTo(C component) {
   if (components.isEmpty()) 
      enableSubscription();
   components.add(component);
}

public void unsubscribeFrom(C component) {
   components.remove(component);
   if (components.isEmpty()) 
      disableSubscription();
}

答案 1 :(得分:1)

我将使用System.gc();

这篇相关文章中有一些非常有趣的信息: Java: How do you really force a GC using JVMTI's ForceGargabeCollection?

显然,许多IDE也使用它来评估可用堆的数量。猜猜我没有理由不这样做。

答案 2 :(得分:0)

也许我们可以先澄清您的架构。你有:

  1. 数据生产者(P)
  2. 许多消费者(C)
  3. 许多“使用”消费者的组件。
  4. 我想知道的是 - 从组件到消费者的关系是什么?您所说的只是有多个组件使用单个消费者。

    一般来说,如果系统中只有P和Cs,那么你就可以让C取消自我注册并完成(正如彼得在他的例子中所示)。但是,在这种情况下,许多组件都使用C.我猜你的架构知识有限,我建议你在需要的时候让每个C注册和取消注册组件,C可以取消注册当所有组件取消注册时,它本身来自P.

答案 3 :(得分:0)

通过调用System.gc()建议到VM,它应该对内存情况做些什么。我引用了javadoc:

  

当控制从方法调用返回时,Java虚拟机已尽最大努力从所有丢弃的对象中回收空间。

请注意,这并不意味着它实际上已经执行了GC,它只是检查它是否需要。在实践中,我还没有看到VM忽略System.gc()调用。

通常你不必也不应该这样做。与您(和我)相比,VM对内存子系统的行为有了更好的理解。但是,在某些情况下,如果应用程序行为不常见且您知道需要内存,则可以这样做。

答案 4 :(得分:0)

您无法强制JVM进行垃圾回收,您可以通过调用System.gc()来建议它。

也许一个更好的解决方案是引入某种类型的Listener模式,你的Cs注册/注销数据生成器和注册你的C的独立组件。当你从C注销时,它可以检查它是否为no需要更长时间,在这种情况下,它可以从数据生产者注销。