Tôi đã bỏ qua cuộc gọi ExceptionCheck()
sau mỗi cuộc gọi JNI và kiểm tra mọi nỗ lực không thành công để định vị phương thức ngắn gọn: bạn nên thêm những điều này khi triển khai.
Đầu tiên, lưu trữ các ngoại lệ và sau đó mua lại các phương thức Java cần thiết cho việc thu thập thông tin về Throwable
:
// Get the exception and clear as no
// JNI calls can be made while an exception exists.
jthrowable exception = pEnv->ExceptionOccurred();
pEnv->ExceptionClear();
jclass throwable_class = pEnv->FindClass("java/lang/Throwable");
jmethodID mid_throwable_getCause =
pEnv->GetMethodID(throwable_class,
"getCause",
"()Ljava/lang/Throwable;");
jmethodID mid_throwable_getStackTrace =
pEnv->GetMethodID(throwable_class,
"getStackTrace",
"()[Ljava/lang/StackTraceElement;");
jmethodID mid_throwable_toString =
pEnv->GetMethodID(throwable_class,
"toString",
"()Ljava/lang/String;");
jclass frame_class = pEnv->FindClass("java/lang/StackTraceElement");
jmethodID mid_frame_toString =
pEnv->GetMethodID(frame_class,
"toString",
"()Ljava/lang/String;");
Thứ hai, đệ quy xây dựng được thông báo lỗi (bạn có thể muốn thay đổi này):
std::string error_msg; // Could use ostringstream instead.
_append_exception_trace_messages(*pEnv,
error_msg,
exception,
mid_throwable_getCause,
mid_throwable_getStackTrace,
mid_throwable_toString,
mid_frame_toString);
void _append_exception_trace_messages(
JNIEnv& a_jni_env,
std::string& a_error_msg,
jthrowable a_exception,
jmethodID a_mid_throwable_getCause,
jmethodID a_mid_throwable_getStackTrace,
jmethodID a_mid_throwable_toString,
jmethodID a_mid_frame_toString)
{
// Get the array of StackTraceElements.
jobjectArray frames =
(jobjectArray) a_jni_env.CallObjectMethod(
a_exception,
a_mid_throwable_getStackTrace);
jsize frames_length = a_jni_env.GetArrayLength(frames);
// Add Throwable.toString() before descending
// stack trace messages.
if (0 != frames)
{
jstring msg_obj =
(jstring) a_jni_env.CallObjectMethod(a_exception,
a_mid_throwable_toString);
const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0);
// If this is not the top-of-the-trace then
// this is a cause.
if (!a_error_msg.empty())
{
a_error_msg += "\nCaused by: ";
a_error_msg += msg_str;
}
else
{
a_error_msg = msg_str;
}
a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str);
a_jni_env.DeleteLocalRef(msg_obj);
}
// Append stack trace messages if there are any.
if (frames_length > 0)
{
jsize i = 0;
for (i = 0; i < frames_length; i++)
{
// Get the string returned from the 'toString()'
// method of the next frame and append it to
// the error message.
jobject frame = a_jni_env.GetObjectArrayElement(frames, i);
jstring msg_obj =
(jstring) a_jni_env.CallObjectMethod(frame,
a_mid_frame_toString);
const char* msg_str = a_jni_env.GetStringUTFChars(msg_obj, 0);
a_error_msg += "\n ";
a_error_msg += msg_str;
a_jni_env.ReleaseStringUTFChars(msg_obj, msg_str);
a_jni_env.DeleteLocalRef(msg_obj);
a_jni_env.DeleteLocalRef(frame);
}
}
// If 'a_exception' has a cause then append the
// stack trace messages from the cause.
if (0 != frames)
{
jthrowable cause =
(jthrowable) a_jni_env.CallObjectMethod(
a_exception,
a_mid_throwable_getCause);
if (0 != cause)
{
_append_exception_trace_messages(a_jni_env,
a_error_msg,
cause,
a_mid_throwable_getCause,
a_mid_throwable_getStackTrace,
a_mid_throwable_toString,
a_mid_frame_toString);
}
}
}
Tôi đã sao chép mã này từ mã tôi đã viết vài năm trước (sửa đổi để loại bỏ tấm nồi hơi ExceptionCheck()
s), nhưng tôi không biên dịch những gì tôi đã đăng nhưng cách tiếp cận chung là hy vọng rõ ràng.
Nếu tất cả bạn cần là đầu ra thông tin này để thiết bị lỗi chuẩn cho mục đích gỡ lỗi, bạn có thể sử dụng ExceptionDescribe() phương pháp tiện lợi. –
Điều đó dường như không làm gì trong C++. Trong trường hợp của tôi, C++ là tệp thực thi và Java được nạp trong ngữ cảnh của ứng dụng C++ đang chạy. –
Nó thực hiện chính xác điều tương tự như 'exc.printStackTrace()'. – EJP