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