5

Linux coredump 或 Windows minidump 的 Java 等价物是什么?我读过关于堆转储的内容,它看起来像我想要的,但是如何在未捕获的异常上(自动)触发它们?

我知道未捕获的异常处理程序,并且我已经在使用它来打印异常+堆栈跟踪并终止整个应用程序(否则线程死亡并且应用程序继续运行?嗯?)我还发现了这篇关于如何记录堆的帖子从代码中转储,但是如果我从未处理的异常处理程序中执行此操作,Java 已经捕获了异常并且堆栈跟踪(和参数)消失了。

我遇到了-XX:+HeapDumpOnOutOfMemoryError似乎可以满足我需要的标志,不幸的是仅针对内存不足的异常,而不针对其他未捕获的异常。

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

[动机更新]

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

4

3 回答 3

2

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

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

如果抛出异常的代码不受您的控制并且您无权访问源代码,那么您可以使用 AspectJ 来编织一些关于该方法抛出异常的建议,然后您可以检查函数参数方面并记录它们。但是在您进行路由 aspectJ / 字节代码编织之前,您可能想查看您尝试理解的代码是否使用 log4j 或其他具有调试日志记录级别的日志框架,这可能会包含您正在寻找的信息。

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

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

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

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

于 2012-12-17T05:32:57.730 回答
0

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

这正是您想要使用它们的目的吗?也许有一种替代但更好的方法来满足您在 java 中的需求。我认为我从来没有需要像 java 的核心或小型转储之类的东西。除了我希望有一种方法可以调用 abort() 只是为了能够研究代码如何最终到达它的位置的情况除外。

于 2012-12-16T22:23:18.047 回答
0

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

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

它本质上使用热点com.sun.management.HotSpotDiagnosticMXBean及其dumpHeap()方法。它可能只适用于 Oracle/Sun JVM,并且不能保证它会在遥远的将来运行。

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

于 2012-12-17T05:49:08.547 回答