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

use*_*433 5 java jvm heap-dump

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

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

谁能帮我?

编辑:重要的是该技术可通过命令行或类似方式使用,因为我需要自动化。不能使用 GUI

apa*_*gin 5

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

以下是此类 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;
}
Run Code Online (Sandbox Code Playgroud)

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

java -agentpath:/path/to/libdump.so MainClass
Run Code Online (Sandbox Code Playgroud)

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


ash*_*ish -1

我想推荐Java Visual VM。它可以动态连接。我发现它很有用。您可能想尝试一下。