2014-05-09 13 views
5

Tôi tự hỏi là có thể ghi lại mọi ngoại lệ xảy ra trên cấp JVM mà không thay đổi mã ứng dụng? Bởi tất cả các ngoại lệ, tôi có nghĩa là bị bắt và uncaught ngoại lệ ... Tôi muốn phân tích những bản ghi sau đó và nhóm chúng theo loại ngoại lệ (lớp) và chỉ cần đếm ngoại lệ theo loại. Tôi đang sử dụng HotSpot;)Truy cập ngoại lệ Java trên JVM HotSpot

Có thể có thông minh hơn về lý do làm việc đó? Ví dụ bằng bất kỳ hồ sơ miễn phí (YourKit có nó nhưng nó không phải là miễn phí)? Tôi nghĩ rằng JRockit có ngoại lệ truy cập trong giao diện điều khiển quản lý, nhưng không thấy bất cứ điều gì tương tự cho HotSpot.

+0

Theo ngoại lệ mặc định được gửi tới stderr; do đó nếu bạn chuyển hướng stderr bạn sẽ nhận được ngoại lệ của bạn bất cứ nơi nào nó được chuyển hướng. – fge

+0

@fge nhưng sau đó anh ta sẽ không thấy ngoại lệ nơi bị bắt và không in. –

+0

@ Absurd-Mind ah vâng, tôi không thấy phần đó ... À, ngắn hạn khi thiết kế mã, tôi không thấy cách nào để làm điều đó – fge

Trả lời

5

Tôi tin rằng có những công cụ miễn phí để làm điều đó, nhưng thậm chí làm cho công cụ của riêng bạn trở nên dễ dàng. JVMTI sẽ trợ giúp.

Dưới đây là một tác nhân JVMTI đơn giản tôi đã thực hiện để theo dõi tất cả các trường hợp ngoại lệ:

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

Để sử dụng nó, tạo ra một thư viện chia sẻ (.so) từ mã nguồn nào đó, và chạy Java với -agentpath tùy chọn:

java -agentpath:libextrace.so MyApplication 

Thao tác này sẽ ghi lại tất cả tên lớp ngoại lệ trên giá trị chuẩn. ExceptionCallback cũng nhận được một chuỗi, một phương pháp và một vị trí mà trường hợp ngoại lệ xảy ra, vì vậy bạn có thể mở rộng gọi lại để in nhiều chi tiết hơn.

+0

Tôi tự hỏi là nó có thể đạt được chức năng tương tự với java instrumentation? (java.lang.instrument) – user1058831

+2

@ user1058831 Thiết bị đo đạc cho phép bạn sửa đổi bytecode Java, nhưng không phải tất cả ngoại lệ đều đến từ bytecode 'athrow'. Một số người trong số họ được ném bởi mã thư viện bản địa và một số được đưa ra bởi JVM. Điều gần nhất bạn có thể làm bằng thiết bị đo đạc có lẽ là đề xuất của Peter về việc sửa đổi constructor 'Throwable'. Một nhân viên JVMTI cùng một lúc sẽ tự động xử lý tất cả các trường hợp. – apangin

Các vấn đề liên quan