Exception上的JVMTI堆转储 - 堆栈跟踪问题

时间:2015-06-23 11:29:28

标签: java jvmti

我一直在摆弄JVMTI API,尝试写一些有用的东西。将来自其他SO问题的代码粘贴在一起,我试图创建一个简单的工具,当发生某种特殊类型的异常时,它会转储堆,这可能在创建jdb监听器很难的环境中很有用。提到的代码:

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

JNIEXPORT void* JNICALL JVM_GetManagement(jint version);
jvmtiEnv* jvmti;

void JNICALL
Exception(jvmtiEnv *jvmti_env,
            JNIEnv* jni_env,
            jthread thread,
            jmethodID method,
            jlocation location,
            jobject exception,
            jmethodID catch_method,
            jlocation catch_location) {
    char *exception_signature;

    /* Obtain signature of the exception and compare type name with FNFE */
    jclass class = (*jni_env)->GetObjectClass(jni_env, exception);
    (*jvmti)->GetClassSignature(jvmti_env, class, &exception_signature, NULL);
    if (strcmp("Ljava/io/FileNotFoundException;", exception_signature)==0) {
        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) {
    (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0);

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

    return 0;
}

这样的过程正在发挥作用;我在一个简单的测试程序上尝试这个代码时得到一个堆转储(打印几行并在它们之间生成异常)。问题是,Eclipse MAT中的线程堆栈分析显示了使用DestroyJavaVM而不是main方法的堆栈跟踪,这与使用jmap生成的堆转储不同。我希望堆转储与jmap不同,因为它是一个JNI调用'中断'已检测线程的正常执行,但不会破坏整个跟踪,只是本机调用位于堆栈顶部。

为什么会这样,我能以某种方式阻止这个问题,并以我喜欢的方式转储堆吗?或者我的整个推理是错误的,这是不可能的?

0 个答案:

没有答案