لماذا قانون بلدي JNI لم يجد بنجاح طريقة getMessage على jthrowable على ذلك؟
-
03-07-2019 - |
سؤال
وأنا أحاول الوصول إلى الرسالة في jthrowable حين تسليم استثناء ولدت عندما تفشل في العثور على الطبقة. ومع ذلك، أنا غير قادر على الوصول إلى ID رسالة getMessage () على الكائن jthrowable، وأنا لا أعرف لماذا. لقد حاولت تغيير توقيع getMessage إلى "() Ljava / انج / سلسلة" (بدون منقوطة في نهاية المطاف، ولكن ما هو ضروري، أليس كذلك؟) مع أي فرح. أنا مرتبك كما الجحيم حول هذا الموضوع. حتى حاولت استبدال getMessage مع toString و <م> أن م> لم تنجح. ومن الواضح أن أفعله شيء مسلي الخطأ هنا.
وهنا هو رمز أنا باستخدام:
jthrowable java_exception;
jclass java_class;
jmethodID method;
java_exception = (*jEnv)->ExceptionOccurred(jEnv);
assert (java_exception != NULL);
java_class = (*jEnv)->GetObjectClass (jEnv, java_exception);
assert (java_class != NULL);
method = (*jEnv)->GetMethodID (jEnv, java_class, "getMessage", "()Ljava/lang/String;");
if (method == NULL) {
printf ("Seriously, how do I get here?!\n");
(*jEnv)->ExceptionDescribe (jEnv);
return;
}
والناتج من هذا الرمز (بين أمور أخرى) يبدو مثل هذا:
<اقتباس فقرة> وعلى محمل الجد، كيف يمكنني الحصول على هنا ؟!
استثناء في موضوع "الرئيسي" java.lang.NoClassDefFoundError: كوم / كوكب / core360 / docgen / المعالج
وjavap -p -s java.lang.Throwable
يعطيني هذا:
وجمعت من "Throwable.java"
الطبقة العامة java.lang.Throwable يمتد java.lang.Object تنفذ java.io.Serializable {
...
الجمهور java.lang.String getMessage ()؛
التوقيع: () Ljava / انج / سلسلة،
...
المحلول
حسنا، لذلك يبدو كانت مشكلتي أن GetObjectClass
لا تتصرف بالطريقة التي تتوقعها لفي jthrowable، أو على الأقل نتائج ذلك ليست مفيدة لأغراض طرق الحصول على. الاستعاضة عن ذلك جزء من الشفرة مع هذا يعمل:
java_class = (*jEnv)->FindClass (jEnv, "java/lang/Throwable");
method = (*jEnv)->GetMethodID (jEnv, java_class, "getMessage", "()Ljava/lang/String;");
والغريب مستحقا للعنة، ذلك. آمل أن يساعد هذا شخص آخر في المستقبل، وإن كان.
نصائح أخرى
وحاولت نهجكم، وأنها عملت لي. وهناك أشياء قليلة على الرغم من: أنا باستخدام واجهة C ++ (على الرغم من أنه لا ينبغي أن تحدث فرقا)، وأنا باستخدام جافا 6 تحديث 10، الإصدار x64، على أوبونتو 8.04. ولعل نسخة جافا و / أو منصة تستخدم سيحدث فرقا.
#include <cstdio>
#include <jni.h>
int
main(int argc, char** argv)
{
if (argc != 3) {
std::fprintf(stderr, "usage: %s class message\n", argv[0]);
return 1;
}
JavaVM* jvm;
void* penv;
JavaVMInitArgs args = {JNI_VERSION_1_6};
if (jint res = JNI_CreateJavaVM(&jvm, &penv, &args)) {
std::fprintf(stderr, "Can's create JVM: %d\n", res);
return -res;
}
JNIEnv* env(static_cast<JNIEnv*>(penv));
jint vers(env->GetVersion());
std::printf("JNI version %d.%d\n", vers >> 16, vers & 0xffff);
env->ThrowNew(env->FindClass(argv[1]), argv[2]);
jthrowable exc(env->ExceptionOccurred());
std::printf("Exception: %p\n", exc);
if (exc) {
jclass exccls(env->GetObjectClass(exc));
jclass clscls(env->FindClass("java/lang/Class"));
jmethodID getName(env->GetMethodID(clscls, "getName", "()Ljava/lang/String;"));
jstring name(static_cast<jstring>(env->CallObjectMethod(exccls, getName)));
char const* utfName(env->GetStringUTFChars(name, 0));
jmethodID getMessage(env->GetMethodID(exccls, "getMessage", "()Ljava/lang/String;"));
jstring message(static_cast<jstring>(env->CallObjectMethod(exc, getMessage)));
char const* utfMessage(env->GetStringUTFChars(message, 0));
std::printf("Exception: %s: %s\n", utfName, utfMessage);
env->ReleaseStringUTFChars(message, utfMessage);
env->ReleaseStringUTFChars(name, utfName);
}
return -jvm->DestroyJavaVM();
}
ولقد استعملت jnitest java/lang/InternalError 'Hello, world!'
لاختبار نفسي. لا تتردد في محاولة مع أنواع استثناء مختلفة!