如何改进应用程序以避免堆空间问题

F.P*_*F.P 6 java memory heap object

我有一个应用程序,它与许多在方法中创建的自定义对象一起工作,并且从不需要在它们之外.整个结构(在我看来)非常好的面向对象,并使用服务,实用程序和DI模型.

现在,当我运行我的第一个"大型"测试时,我很快遇到了OutOfMemoryExceptions.现在,我不只是想增加堆空间并完成它,因为我可以想象这不会解决问题,而是延迟它直到我的应用程序增长更多并遇到同样的问题.

我正在寻找一些简单易用的解决方案,技巧和片段,它们可以帮助应用程序处理垃圾收集和堆空间,尤其是涉及许多使用对象创建操作的循环时.

像"不要在循环中创建对象,在循环之前创建它们并在其中覆盖它"之类的东西.

Mik*_*unu 5

一些要点:

  • 增加堆空间没有任何根本性的错误.不同的应用往往有不同的要求.
  • 使用分析器来查看实际发生的情况.例如,您可以在这里找到堆分析器:MAT
  • 当您发现某些类的实例负责80%的堆消耗时:
    • 尝试找到具有相同值的共同变量集.那些候选者是一个可以由多个对象共享的对象.
    • 检查特别是你将一些对比较大的对象图的引用存储到比你的循环长得多的变量(局部变量消耗堆栈).
    • 让引用尽快退出范围.
    • 如果使用内部类,请检查非内部类,因为非静态内部类保持对包含对象的引用.

  • +1用于引用内部类.他们有很多陷阱,大多数人都不知道...... (2认同)

Nig*_*olf 2

我将首先分析您的应用程序并使用 jvisualvm(JDK 的一部分)查找内存热点。这将为您提供对象有多大以及哪些方法调用导致高内存使用的指示。它还会告诉您对象在内存中停留的时间,这通常是一个很好的起点,因为您希望将范围缩小到尽可能短。

下一步是通过改进设计或实现缓存来识别对象的共性。如果您从固定存储加载数据,那么您可以使用软引用,以便当 JVM 耗尽堆时,这些对象将被 GC(如果您对这些对象进行更改,则显然需要在删除硬引用之前保留它们)。然后,如果再次需要它们,您的应用程序将只需要从后备存储(数据库、文件或其他)重新加载它们。

确保您了解 GC 的工作原理并了解您的对象引用:

  • 强/直接
  • 柔软的
  • 虚弱的
  • 幻影

以下是一些解释引用和 GC 的好文章:

http://www.java-tips.org/java-se-tips/java.util/using-weakhashmap-for-listener-lists.html

http://pawlan.com/monica/articles/refobjs/

http://www.kdgregory.com/index.php?page=java.refobj