我注意到,有时候,当内存几乎耗尽时,GC会尝试以任何性能价格完成(导致程序几乎冻结,有时多分钟),而不是只需立即抛出OOME(OutOfMemoryError)。
有没有办法在这方面调整GC?
将程序降低到接近零速度会使其无响应。在某些情况下,最好是回复“我死了”,而不是根本没有回应。
答案 0 :(得分:8)
像你所追求的东西被内置到最近的JVM中。
如果你:
UseGCOverheadLimit
(默认情况下,这些收集器已启用,因此更具体地说,如果您没有禁用它)然后你会在实际耗尽内存之前获得一个OOM:如果最近98%的时间花在了GC上以恢复<2%的堆大小,那么你将获得一个抢先的OOM。 / p>
调整这些参数(特别是98%)听起来对你有用,但是据我所知,没有办法调整这些阈值。
但是,请检查您是否符合上述三点要求;如果您没有使用带有该旗帜的收藏家,这可能有助于您的情况。
值得一读the HotSpot JVM tuning guide,这对这些东西有很大的帮助。
答案 1 :(得分:2)
我不知道以您描述的方式配置Java垃圾收集器的任何方法。
一种方法可能是您的应用程序主动监控可用内存量,例如:使用Runtime.freeMemory()
,并声明“我死了”条件,如果它低于某个阈值并且无法通过强制垃圾回收周期进行纠正。
我们的想法是选择足够大的阈值,使流程永远不会陷入您描述的情况。
答案 2 :(得分:1)
我强烈建议不要这样做,Java尝试GC而不是立即抛出OutOfMemoryException更有意义 - 除非每个替代方案已经用尽,否则不要让你的应用程序崩溃。
如果你的应用程序内存不足,你应该增加最大堆大小,或者根据内存分配查看它的性能,看看它是否可以优化。
要注意的一些事情是:
编辑:我认为你误解了我的观点。如果您不小心将实时引用留给了不再需要使用的对象,那么显然仍然不会进行垃圾回收。这与使用null-only无关 - 这是一个典型的例子,它将使用一个大对象用于特定目的,但是当它超出范围时它不是GC,因为实时引用意外地遗留在别处,某处你不知道造成泄漏。一个典型的例子是哈希表查找,可以用弱引用来解决,因为只有弱可达时才有资格获得GC。
无论这些只是关于如何通过内存分配提高性能的一般想法。我试图提出的问题是,询问如何更快地抛出OutOfMemory错误,而不是让Java GC尝试最好释放堆上的空间,这不是一个好主意IMO。改为优化您的应用程序。
答案 3 :(得分:0)
事实证明,自 Java8 b92 以来,有一种解决方案:
-XX:+ExitOnOutOfMemoryError
启用此选项后,JVM会在第一次出现内存不足错误时退出。如果您希望重新启动JVM实例而不是处理内存不足错误,可以使用它。
-XX:+CrashOnOutOfMemoryError
如果启用此选项,则当发生内存不足错误时,JVM崩溃并生成文本和二进制崩溃文件(如果启用了核心文件)。
一个好主意是将上述选项之一与旧的-XX:+HeapDumpOnOutOfMemoryError
我测试了这些选项,它们实际上按预期运行!