Java:在独立运行之间清除内存

Java:在独立运行之间清除内存,java,loops,garbage-collection,out-of-memory,Java,Loops,Garbage Collection,Out Of Memory,我在Java中实现了一个启发式算法,用于解决给定输入的优化问题。启发式可以运行数千次迭代,并创建许多复杂度不同的对象 为了测试它,我有数千个测试输入。我的主要方法接受所有输入,并在循环中为每个输入顺序启动启发式。对于每个输入,结果存储在单独的文件中 当我运行程序时,它总是在生成218或219后停止,并抛出一个“OutOfMemoryError”。一旦它在线程“main”java.lang.OutOfMemoryError中显示了异常:GC开销超出了限制,并且线程“main”java.lang.O

我在Java中实现了一个启发式算法,用于解决给定输入的优化问题。启发式可以运行数千次迭代,并创建许多复杂度不同的对象

为了测试它,我有数千个测试输入。我的主要方法接受所有输入,并在循环中为每个输入顺序启动启发式。对于每个输入,结果存储在单独的文件中

当我运行程序时,它总是在生成218或219后停止,并抛出一个“OutOfMemoryError”。一旦它在线程“main”java.lang.OutOfMemoryError中显示了
异常:GC开销超出了限制
,并且线程“main”java.lang.OutOfMemoryError中显示了
异常:java堆空间

我的猜测是,程序会随着时间的推移创建太多的对象,直到在计算第218或第219次输入时内存耗尽为止。每个实例都在独立运行中计算。因此,在存储输入的结果之后,在解析下一个输入之前,应该清除内存并清除所有创建的对象。对吗?我听说使用是不好的做法,但是对于我的情况,你还有什么建议吗

编辑: 为了指定我想要的:我没有为每个输入按“开始”,而是实现了循环来为我做这件事。但是,它的行为似乎不一样,它会保留以前运行的旧对象。我是否可以更改java代码,使其行为类似于为每个输入重新启动程序?或者我必须使用一个shell脚本,分别为每个输入启动启发式,使其工作? 我从未使用过任何JVM参数,在我看来,它们似乎并没有真正解决这个问题


已解决:事实上,我发现并修复了一个内存泄漏。不需要System.gc()。无论如何谢谢你的帮助

是,将GC处理留给JVM。您需要遵循以下提到的一些步骤,以便:

  • 使用Xmx增加堆大小。。。参数
  • 设置合适的GC算法和参数。如果已经有GC参数,请尝试调整
  • 在启动JVM时,请尝试使用-XX:+HeapDumpOnOutOfMemoryError和-XX:HeapDumpPath=选项,以便在JVM运行时获得堆转储。通过使用堆转储,您可以使用诸如jprofiler/yourkit/jvisualvm等探查器来调查内存泄漏,然后对其进行纠正
首先,当启动JVM运行测试时,禁用GC开销限制:

-XX:-UseGCOverheadLimit
我建议这样做,因为您已经知道您有意对垃圾收集器施加压力,并且不希望它警告您GC开销

第二,看看如何更好地分解测试,这样可以允许对来自上一个测试的对象进行垃圾收集。在每次测试完成后,不要保留指向大型对象结构的活动指针

第三,如果由于超出
Java堆空间
,仍然需要更多内存,请使用:

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
通常不建议将其设置为低于
2
(2/3旧,1/3新),但在您的情况下,我可能建议您尝试将其设置为
1
(1/2旧,1/2新)

另请参见并查看。

尝试一下:

从网站:

使用类似System.gc()的函数;或Runtime.getRuntime().gc();只建议JVM运行垃圾收集器。 我在互联网上找到了一种方法,不强制抓取收集器,而是等待垃圾收集器运行


您可以捕获OutOfMemoryError,但不应该捕获(无论如何,您不能对此做任何事情)。您有两种选择:使用额外的堆空间运行Java
-Xmx2048m
,或者调试代码以避免在堆上留下这么多对象。使用完未使用的对象后,将其设置为
null
。是的,不要调用
System.gc()
,这对您没有帮助。如果以前输入的对象仍保留在堆上,则额外的堆空间也不会有帮助。它只会延迟OutOfMemoryError。将我不再需要的所有对象设置为
null
似乎很奇怪,而且需要付出很多努力。在每次运行之后清理所有东西会更好,一旦JVM启动并完成了大量的工作,就没有办法将其恢复到“原始”状态。但是,如果您声称代码的每个迭代都是“独立的”,但您仍然得到OOM,那么您声称的独立性是错误的,并且您在迭代之间以某种方式依赖于结果。(您不需要将所有对象设置为null(即使这在某种程度上是可能的)。你只需要确保你没有意外地或有意地通过链表、从未清除的地图或类似的东西来维护以前跑步的“历史记录”。)我知道这很旧,但我面临着类似的问题,我想也是出于类似的原因。想分享一下你的内存泄漏的地方吗?
-XX:NewRatio=<n>   Ratio of old/new generation sizes. The default value is 2.