2014-05-09 32 views
5

Uygulama kodunu değiştirmeden JVM seviyesinde gerçekleşen her özel durumun günlüğe kaydedilmesi mümkün mü acaba? Her istisna ile yakalanmış ve yakalanmamış istisna demek istiyorum ... Bu günlükleri daha sonra analiz etmek ve istisna tipi (sınıf) ile gruplamak ve sadece türlere göre istisnaları saymak istiyorum. HotSpot kullanıyorum;)JVM HotSpot'ta Java Özel Durumlar sayacı

Belki de bunu neden daha akıllıca yapıyoruz? Örneğin herhangi bir ücretsiz profiler tarafından (YourKit var ama ücretsiz değil)? JRockit'in yönetim konsolunda istisna sayacı olduğunu düşünüyorum, ancak HotSpot için benzer bir şey görmüyorum.

+0

Varsayılan olarak stderr; Bu nedenle, stderr'i yeniden yönlendirirseniz, yeniden yönlendirdiğiniz her yerde istisnalarınızı almalısınız. – fge

+0

@fge ancak o zaman yakalanan ve basılmayan istisnalar görmeyecek. –

+0

@ Absurd-Mind ah evet, ben bu kısmı görmedim ... Eh, kodu enstrümantasyonun kısa bir yolu – fge

cevap

5

Bunu yapmak için ücretsiz araçlar olduğuna inanıyorum, hatta kendi aracınızı yapmak bile kolay. JVMTI yardımcı olacaktır. İşte

Bütün istisnalar izlemek için yapılmış basit bir JVMTI ajandır:

#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; 
} 

Kullanmak için, verilen kaynak kodundan paylaşılan kitaplığı (bu nedenle) yapmak ve -agentpath seçeneğiyle Java çalıştırın:

Bu, stdout'taki tüm özel durum sınıf adlarını günlüğe kaydeder. ExceptionCallback ayrıca bir iş parçacığı, bir yöntem ve özel durumun oluştuğu bir yer alır, böylece geri bildirimi daha fazla ayrıntıyı yazdırmak için genişletebilirsiniz.

+0

Ben java enstrümantasyon ile benzer işlevsellik elde etmek mümkün mü acaba? (java.lang.instrument) – user1058831

+2

@ user1058831 Enstrümantasyon, Java bayt kodunu değiştirmenize izin verir, ancak tüm istisnalar 'athrow' bytecode'dan gelmez. Bazıları yerel kütüphane kodu ile atılır ve bazıları JVM tarafından gizli olarak atılır. Enstrümantasyon ile yapabileceğiniz en yakın şey, muhtemelen Peter'ın 'Throwable' kurucusunu değiştirmeye yönelik önerisidir. Aynı zamanda JVMTI aracı tüm vakaları otomatik olarak ele alacaktır. – apangin