Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中处理内存不足情况的最佳方法是什么?_Java_Linux_Process_Garbage Collection_Out Of Memory - Fatal编程技术网

在Java中处理内存不足情况的最佳方法是什么?

在Java中处理内存不足情况的最佳方法是什么?,java,linux,process,garbage-collection,out-of-memory,Java,Linux,Process,Garbage Collection,Out Of Memory,我们有一个生成新JVM并代表用户执行代码的应用程序。有时,这些内存会耗尽,在这种情况下,它们的行为方式会截然不同。有时他们抛出一个OutOfMemoryError,有时他们冻结。我可以通过一个非常轻量级的后台线程来检测后者,该线程在内存不足时停止发送心跳信号。在这种情况下,我们杀死了JVM,但我们永远无法绝对确定无法接收心跳信号的真正原因是什么。(也可能是网络问题或细分故障。) 可靠地检测JVM内存不足情况的最佳方法是什么 理论上,-XX:OnOutOfMemoryError选项看起来很有希望

我们有一个生成新JVM并代表用户执行代码的应用程序。有时,这些内存会耗尽,在这种情况下,它们的行为方式会截然不同。有时他们抛出一个OutOfMemoryError,有时他们冻结。我可以通过一个非常轻量级的后台线程来检测后者,该线程在内存不足时停止发送心跳信号。在这种情况下,我们杀死了JVM,但我们永远无法绝对确定无法接收心跳信号的真正原因是什么。(也可能是网络问题或细分故障。)

可靠地检测JVM内存不足情况的最佳方法是什么

  • 理论上,-XX:OnOutOfMemoryError选项看起来很有希望,但由于以下缺陷,它实际上无法使用:

  • 出于众所周知的原因(例如,你永远不知道它发生在哪里),捕捉OutOfMemoryError实际上不是一个好的选择,尽管它在很多情况下都有效

  • 剩下的情况是JVM冻结并且不会抛出OutOfMemoryError。我仍然相信内存是导致这个问题的原因

是否有其他选择或解决办法?垃圾收集设置使JVM自行终止而不是冻结


编辑:我完全控制forking和forking JVM以及其中执行的代码,两者都在Linux上运行,如果有帮助,可以使用操作系统特定的实用程序。

如果您可以同时控制应用程序和配置,最好的解决方案是找到抛出OutOfMemoryError的根本原因并修复它,而不是试图通过捕获错误或只是重新启动JVM来隐藏症状

从您描述的情况来看,在JVM上运行的应用程序显然是在泄漏内存,只是在使用未充分配置的资源(在您的情况下是内存)运行,或者偶尔处理需要异常大的堆块的事务。针对这些情况的解决方案将有所不同:

  • 如果发生内存泄漏,请找到根本原因并让工程师修复。用于此的工具包括堆转储分析器、分析器或泄漏检测器
  • 在资源配置不足的情况下,您需要监控应用程序内存消耗,例如通过垃圾收集日志,并根据您面临的问题调整不同内存池的大小
  • 如果在用户事务处理期间出现激增分配,您需要跟踪导致激增的代码,并让工程师修复——通过禁用某些用户输入或以较小的批量加载和处理数据。进程中的线程转储或堆转储都可以指导您找到解决方案
  • 唯一的实际选择是(不幸的)尽快终止JVM

    因为您可能无法更改所有代码以捕获错误并作出响应。如果您不信任OnAutofMemoryError(我想知道为什么它不应该使用Java 8使用的vWork,它可以在Windows上工作),您至少可以触发heapdump并从外部监视这些文件:

    java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
    

    经过一段时间的试验,这是一个对我们有效的解决方案:

  • 在生成的JVM中,捕获一个
    OutOfMemoryError
    并立即退出,用退出代码向控制器JVM发送内存不足的信号
  • 在生成的JVM中,定期检查当前运行时消耗的内存量。当使用的内存量接近临界值时,创建一个标志文件,向控制器JVM发送内存不足的信号。如果我们从这种情况下恢复并正常退出,请在退出之前删除该文件
  • 在控制JVM加入分叉JVM之后,它检查步骤(1)中生成的退出代码和步骤(2)中生成的标志文件。除此之外,它还检查文件
    hs_err_pidXXX.log
    是否存在并包含行“内存不足错误”。(此文件由java生成,以防崩溃。)
  • 只有在实现了所有这些检查之后,我们才能处理分叉JVM内存不足的所有情况。我们认为,自那时以来,我们从未错过过发生这种情况的案例

    java标志
    -XX:onAutofmemoryError
    由于fork问题而未使用,并且
    -XX:+heapdumpOnAutofmemoryError
    未使用,因为堆转储超出了我们的需要


    解决方案当然不是有史以来编写的最优雅的代码,但它为我们完成了任务。

    听起来您真正感兴趣的是检测另一个进程何时出现内存不足;这是一个关键点,你的问题标题甚至没有暗示。谢谢。我试图在文章中更清楚地说明这一点,但到目前为止我还没有改变标题,因为我能想到的所有替代标题都是误导性的。特别是,我不介意我们是从JVM内部、从调用JVM获得信息,还是将其视为具有特定行为的JVM,或者仅仅将其视为一个过程。如果你不改进你的标题,许多能够回答的人甚至不太可能打开你的帖子。“如果Java VM进程内存不足,则触发警报”可能是一个更好的标题,“捕获OutOfMemoryError”-我想,您已经在使用
    setDefaultUncaughtExceptionHandler
    ,对吗?理论上,当OOME发生时,您可以分配几兆字节并释放它们,这样错误处理程序就有更好的生存机会。只是猜测……有关捕获OutOfMemory错误的原因有问题的信息,请参阅我假设OutOfMemory没有单一原因的问题,只是运行了任意用户代码。我认为他不是在问如何修复用户的代码,这是正确的。人们提交工作流(将其视为visua