2015-08-23 57 views
1

如何獲得異常堆棧跟蹤與JVMTI。我爲處理異常寫了簡單的代碼,但我想處理異常行號。如何獲得這個數字?JVMT異常監測器

#include <jvmti.h> 
#include <string.h> 
#include "agent.h" 

void printStackTrace(JNIEnv* env, jobject exception) { 
    jclass throwable_class = (*env).FindClass("java/lang/Throwable"); 
    jmethodID print_method = (*env).GetMethodID(throwable_class, "printStackTrace", "()V"); 
    (*env).CallVoidMethod(exception, print_method); 
} 

void JNICALL ExceptionCallback(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, 
           jmethodID method, jlocation location, jobject exception, 
           jmethodID catch_method, jlocation catch_location) { 
    char* class_name; 
    jvmtiFrameInfo frames[10000]; 
    jint count; 
    jvmtiError err; 

    jclass exception_class = (*env).GetObjectClass(exception); 
    (*jvmti).GetClassSignature(exception_class, &class_name, NULL); 
    printf("Exception: %s\n", class_name); 
    printStackTrace(env, exception); 
    err = (*jvmti).GetStackTrace(thread, 0, 10000, (jvmtiFrameInfo *)&frames, &count); 
    if (err != JVMTI_ERROR_NONE) { 
     printf("(GetThreadInfo) Error expected: %d, got: %d\n", JVMTI_ERROR_NONE, err); 
     printf("\n"); 

    } 
    printf("Number of records filled: %d\n", count); 
} 

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { 
    jvmtiEnv* jvmti; 
    jvmtiEventCallbacks callbacks; 
    jvmtiCapabilities capabilities; 

    (*vm).GetEnv((void**)&jvmti, JVMTI_VERSION_1_0); 

    memset(&capabilities, 0, sizeof(capabilities)); 
    capabilities.can_generate_exception_events = 1; 
    (*jvmti).AddCapabilities(&capabilities); 

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

    return 0; 
} 

回答

1

我按問題解決。只需要添加capabilities.can_get_line_numbers = 1;並調用(* JVMTI) - > GetLineNumberTable(JVMTI,方法,&計數,& location_table);

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

void printStackTrace(JNIEnv* env, jobject exception) { 
    jclass throwable_class = (*env)->FindClass(env, "java/lang/Throwable"); 
    jmethodID print_method = (*env)->GetMethodID(env, throwable_class, "printStackTrace", "()V"); 
    (*env)->CallVoidMethod(env, exception, print_method); 
} 

void JNICALL ExceptionCallback(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, 
           jmethodID method, jlocation location, jobject exception, 
           jmethodID catch_method, jlocation catch_location) { 
    char* class_name; 
    jclass exception_class = (*env)->GetObjectClass(env, exception); 
    (*jvmti)->GetClassSignature(jvmti, exception_class, &class_name, NULL); 


    int count; 
    int line_number = 0; 
    int i; 
    jvmtiLineNumberEntry *location_table; 
    (*jvmti)->GetLineNumberTable(jvmti, method, &count, &location_table); 
    for (i = 0; i < count - 1; i++) 
    { 
     jvmtiLineNumberEntry entry1 = location_table[i]; 
     jvmtiLineNumberEntry entry2 = location_table[i+1]; 
     if (location >= entry1.start_location && location < entry2.start_location) 
     { 
      line_number = entry1.line_number; 
      break; 
     } 
    } 
    if (location >= location_table[count-1].start_location) 
    { 
     line_number = location_table[count-1].line_number; 
    } 

    printf("Exception: %s ", class_name); 
    printf("%d \n", line_number); 
} 

JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { 
    jvmtiEnv* jvmti; 
    jvmtiEventCallbacks callbacks; 
    jvmtiCapabilities capabilities; 

    (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0); 

    memset(&capabilities, 0, sizeof(capabilities)); 
    capabilities.can_generate_exception_events = 1; 
    capabilities.can_get_line_numbers = 1; 
    (*jvmti)->AddCapabilities(jvmti, &capabilities); 

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

    return 0; 
}