我有一个在java(1.6)中运行的关键进程,带有一个注册的关闭钩子。在某些情况下我得到一个OOM问题(下面有关于该问题的更多细节),该过程突然停止,我没有得到任何我的日志,我的捕获(Throable x)没有捕获异常。
但是关机钩子有效。因此,如果有一种方法可以知道由于某些讨厌的OOM而导致进程停止,我可以在退出之前记录必要的信息。
有办法做到这一点吗?
关于OOM : 不知道什么是例外,因为我说它不会被抓住。我知道这是一个OOM因为我用
开始这个过程-XX:+HeapDumpOnOutOfMemoryError
我得到一个堆转储文件。在其他情况下,会捕获异常,并且它是ava.lang.OutOfMemoryError:超出了GC开销限制。但不确定这种情况总是如此。
修改
如果不清楚:我没有尝试阻止OOM,因为在某些情况下可能会出现有效原因,我只是想确保在应用日志文件中清楚
我的问题是:是否有可能在关机钩子中发现由于OOM导致进程正在关闭?
我需要在同一过程以编程方式和执行此操作。
现在最好的方法是查看是否存在process_.hprof(我知道pid)的堆转储文件java_pid_pid,其中包含最近的日期,并推断出有一个OOM。 我想我可以尝试Runtime.getRuntime()。freeMemory()并报告问题,如果可用的内存非常低,但不确定它有多可靠,可能当进程关闭时它已经释放了很多内存,方法以上是我认为最好的。
答案 0 :(得分:3)
OOM很棘手,因为如果JVM内存不足,可能会因为抛出新的OOM而无法运行异常处理代码。
尝试设置default uncaught exception handler。它将捕获所有未被捕获的异常。
答案 1 :(得分:2)
您可以运行另一个监视OOE日志文件的进程(或监视进程是否被终止),然后重新启动进程。
或许将您的应用程序作为Unix deamon或Windows服务更合适。
但是,使用分析工具调查内存泄漏呢?
jvisualvm是一个很好的
答案 2 :(得分:2)
您可能希望查看-XX:OnOutOfMemoryError="cmd_with_pid_arg %p"
选项(命令字符串类似于-XX:OnError
)。
答案 3 :(得分:1)
答案 4 :(得分:0)
你可以(技术上)捕获OutOfMemoryErrors,但是如果没有内存,你不确定你是否能够执行catch块中的代码。
也许值得尝试(1)捕获OOM,(2)触发垃圾收集(System.gc()
)并尝试写入日志或控制台。不保证,但不会破坏任何东西。
答案 5 :(得分:0)
你应该解决问题,而不是试图弥补它。
堆转储将显示消耗最多内存的对象类型。您应该能够确定这些对象的分配位置,或者为什么它们应该被丢弃之后仍然存在。
至于您收到的具体错误,请查看此SO问题:Error java.lang.OutOfMemoryError: GC overhead limit exceeded - 似乎最简单的解决方案是增加堆大小。
答案 6 :(得分:0)
同样,使用jvisualvm(JDK 6,在bin文件夹中)作为其他人或其他分析工具的建议是解决问题而不是处理它的最佳方法,但假设您将分别调查OOM原因,并尝试根除它们,我会考虑做以下POC,(另见Alois回答)
运行一个将包装OOM抛出过程调用的Java进程怎么样?
您可以捕获发送到被调用进程的输出流的任何结果,并查看是否存在可用于标识OOM的一致退出代码/堆栈跟踪
我确信有更多的方法,但在我看来,这似乎是一个好的,程序化的起点