Java相当于未捕获异常的coredump

时间:2012-12-16 22:13:11

标签: java error-handling crash-dumps

Linux coredump或Windows minidump的Java等价物是什么?我已经阅读了堆转储,它看起来像我想要的,但是如何在未捕获的异常中自动触发它们?

我知道未捕获的异常处理程序,我已经用它来打印异常+堆栈跟踪并终止整个应用程序(否则线程死了,应用程序一直在运行?嗯?)我还发现{{3}关于如何从代码中记录堆转储,但是如果我从未处理的异常处理程序那样做,Java已经捕获了异常并且堆栈跟踪(和参数)都消失了。

我遇到-XX:+HeapDumpOnOutOfMemoryError标志,似乎做了我需要的事情,遗憾的是仅用于内存异常,而不是其他未捕获的异常。

到目前为止,这是我唯一能够摆脱谷歌的事情。目前我正在使用带有异常断点的附加调试器,但这是不切实际的,因为它也会中断处理的异常,因此无法在无人监督的情况下使用它。

[动机更新]

我希望能够检查堆栈跟踪的参数和局部变量,以找出导致异常的原因。它通常是空引用异常或断言失败,我不能总是从行号中猜出究竟出了什么问题。在C / C ++中,我习惯于使用coredump / minidump崩溃,然后进一步检查实际导致崩溃的原因。

3 个答案:

答案 0 :(得分:2)

如果您没有使用JNI并调用本机代码,则很难破坏JVM的内存,异常不应该需要堆转储或核心转储。

在java世界中,抛出异常的代码应该为读取异常的某个人提供足够的信息,以便能够确定问题的原因。有时这种情况不会发生,处理它的正确方法是修改异常抛出代码以在异常中提供更多信息或将某些内容记录到日志文件中。

如果抛出异常的代码不在您的控制范围内并且您无法访问源代码,那么您可以使用AspectJ来编织一些方法,向该方法抛出异常然后您可以检查该函数方面中的参数并记录它们。但是在您编写路径aspectJ / byte代码之前,您可能希望查看您尝试理解的代码是使用log4j还是其他具有调试日志记录级别的日志框架,这可能会影响您正在寻找的信息。

您可能需要查看Google Guava开源库,它有一个关于Pre conidtions的很好的部分,您可以使用它来验证参数并获得有关问题原因的更多上下文。 http://code.google.com/p/guava-libraries/wiki/PreconditionsExplained

您还需要查看具有良好日志记录API的http://www.slf4j.org/,您可以使用它来记录有关您遇到的问题的信息。

你也可以在eclipse中做条件断点,这允许你只在某些情况下执行断点。 http://wiki.eclipse.org/FAQ_How_do_I_set_a_conditional_breakpoint%3F

另一个使用的工具是jvisiual vm,它允许你连接到一个实时虚拟机,并找到关于vm内部发生了什么的很多信息,比如所有线程都在哪里,如果有任何死锁,那么GC正在做什么,您可以使用它触发heapdumps然后查询它们并查看堆转储中特定对象的状态。 http://docs.oracle.com/javase/7/docs/technotes/guides/visualvm/index.html

答案 1 :(得分:0)

我认为堆转储不是你想要的。它只是一个堆的转储,打开该开关的原因是,如果你得到一个OOM异常,你可能要调查的一件事是内存的用途,以便你可以找到你的泄漏(或其他问题)。

你想要用它们到底是什么意思?也许有一种替代但更好的方法来满足您在java中的需求。我不认为我曾经需要像java这样的核心或minidump。除了我希望有一种方法可以调用abort()只是为了能够研究代码如何结束它所做的事情。

答案 2 :(得分:0)

Oracle的这篇博客描述了如何以编程方式执行堆转储:

https://blogs.oracle.com/sundararajan/entry/programmatically_dumping_heap_from_java

它主要使用Hotspot的com.sun.management.HotSpotDiagnosticMXBean及其dumpHeap()方法。它可能只适用于Oracle / Sun JVM,并且不保证它将在遥远的未来发挥作用。

然而,困难的部分是,一旦你有这个堆转储如何从中获取有用的信息。我想你会从找到新抛出的异常对象开始,然后从那里开始。堆转储无法帮助您将方法参数和局部变量值作为基元和引用不会出现在堆转储中。