لماذا قانون بلدي JNI لم يجد بنجاح طريقة getMessage على jthrowable على ذلك؟

StackOverflow https://stackoverflow.com/questions/215638

سؤال

وأنا أحاول الوصول إلى الرسالة في 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!' لاختبار نفسي. لا تتردد في محاولة مع أنواع استثناء مختلفة!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top