2014-05-09 9 views
5

Ich frage mich, ist es möglich, jede Ausnahme zu protokollieren, die auf JVM-Ebene auftritt, ohne den Anwendungscode zu ändern? Mit jeder Ausnahme meine ich gefangene und nicht abgefangene Ausnahme ... Ich möchte diese Protokolle später analysieren und sie nach Ausnahmetyp (Klasse) gruppieren und Ausnahmen einfach nach Typ zählen. Ich benutze HotSpot;)Java Exceptions Counter auf JVM HotSpot

Vielleicht gibt es klüger warum es tun? Zum Beispiel mit einem kostenlosen Profiler (YourKit hat es, aber es ist nicht kostenlos)? Ich denke, dass JRockit einen Ausnahmezähler in der Managementkonsole hat, aber für HotSpot nichts Ähnliches sieht.

+0

Standardmäßig werden Ausnahmen an stderr gesendet; Wenn Sie also stderr umleiten, sollten Sie Ihre Ausnahmen erhalten, wo auch immer Sie weitergeleitet wurden. – fge

+0

@fge aber dann wird er keine Ausnahmen sehen, die gefangen und nicht gedruckt wurden. –

+0

@ Absurd-Mind ah yeah, ich habe diesen Teil nicht gesehen ... Nun, ich habe keine Möglichkeit, den Code zu instrumentieren. – fge

Antwort

5

Ich glaube, es gibt kostenlose Tools, um es zu tun, aber sogar ein eigenes Tool zu erstellen ist einfach. JVMTI wird helfen.

Hier ist ein einfaches JVMTI Mittel ich alle Ausnahmen verfolgen gemacht:

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

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); 
    printf("Exception: %s\n", class_name); 
} 


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; 
    (*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; 
} 

, es zu benutzen, machen Sie eine gemeinsam genutzte Bibliothek (.so) aus dem Quellcode gegeben, und führen Sie Java mit -agentpath Option:

java -agentpath:libextrace.so MyApplication 

Dies protokolliert alle Ausnahmeklassennamen auf stdout. ExceptionCallback empfängt auch einen Thread, eine Methode und einen Speicherort, an dem die Ausnahme aufgetreten ist. Sie können den Rückruf so erweitern, dass viel mehr Details gedruckt werden.

+0

Ich frage mich, ist es möglich, ähnliche Funktionalität mit Java-Instrumentierung zu erreichen? (java.lang.instrument) – user1058831

+2

@ user1058831 Instrumentation ermöglicht es Ihnen, Java-Bytecode zu ändern, aber nicht alle Ausnahmen stammen aus 'athrow' Bytecode. Einige von ihnen werden von nativem Bibliothekscode und einige von JVM implizit geworfen. Die nächste Sache, die Sie durch Instrumentierung erreichen können, ist wahrscheinlich Peters Vorschlag, den Throwable-Konstruktor zu modifizieren. Gleichzeitig wird der JVMTI-Agent alle Fälle automatisch bearbeiten. – apangin