在未捕获的异常上生成Java堆转储

时间:2014-05-13 13:30:01

标签: java jvm heap-dump

我尝试在触发未捕获的异常时生成堆转储。我尝试使用jmap,但因为当异常发生时进程已完成,这是不可能的。

使用UncaughtExceptionHandler也不是选项,因为我只有执行程序的二进制文件。

任何人都可以帮助我吗?

编辑:通过命令行或类似方法提供此技术非常重要,因为我需要自动执行此操作。使用GUI是没有选择的

3 个答案:

答案 0 :(得分:1)

尝试将处理放入deamon线程。这样您就可以使用内存分析工具访问它。 JVisualVM是一个JDK工具,您可以在JAVA_HOME \ bin中找到它。

还有另一种方法,称为转储分析器。您使用以下JVM参数运行应用程序:

  • -XX:+ HeapDumpOnOutOfMemoryError

  • -XX:HeapDumpPath =" your_path"

但只有在你有一个OutOfMemoryError时才会使用它。尝试查找是否可以为任何性能生成转储。

另一个基于eclipse的好工具是MemoryAnalyzer

答案 1 :(得分:0)

这可以通过JVMTI代理来实现,该代理将监听VMDeath事件,然后使用JMM interface启动堆转储。

以下是此类JVMTI代理的示例源代码:

#include <jvmti.h>
#include <string.h>
#include <stdio.h>
#include "jmm.h"

JNIEXPORT void* JNICALL JVM_GetManagement(jint version);

void JNICALL VMDeath(jvmtiEnv* jvmti, JNIEnv* jni) {
    JmmInterface* jmm = (JmmInterface*) JVM_GetManagement(JMM_VERSION_1_0);
    if (jmm == NULL) {
        printf("Sorry, JMM is not supported\n");
    } else {
        jstring path = (*jni)->NewStringUTF(jni, "dump.hprof");
        jmm->DumpHeap0(jni, path, JNI_TRUE);
        printf("Heap dumped\n");
    }
}

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    jvmtiEnv* jvmti;
    (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0);

    jvmtiEventCallbacks callbacks;
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.VMDeath = VMDeath;
    (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
    (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);

    return 0;
}

在将其编译到共享库(libdump.so)之后,使用-agentpath选项运行Java:

java -agentpath:/path/to/libdump.so MainClass

如果您希望处理未捕获的异常而不是等待VMDeath,您可以使用类似的技术来安装Exception事件的回调。请查看here示例。

答案 2 :(得分:-1)

我想建议Java Visual VM。它可以动态连接。我发现它很有用。你可能想尝试一下。