7 Stimmen

Warum findet mein JNI-Code nicht erfolgreich die getMessage-Methode von jthrowable?

Ich versuche, die Nachricht in einem jthrowable zugreifen, während die Übergabe einer Ausnahme erzeugt, wenn ich eine Klasse zu finden, nicht. Ich kann jedoch nicht auf die Nachrichten-ID von getMessage() auf dem jthrowable-Objekt zugreifen, und ich weiß nicht, warum. Ich habe versucht, die Signatur von getMessage in "()Ljava/lang/String" zu ändern (ohne das Semikolon am Ende, aber das ist doch notwendig, oder? Ich bin verdammt verwirrt darüber. Ich habe sogar versucht, getMessage durch toString zu ersetzen, und que hat nicht funktioniert. Offensichtlich mache ich hier etwas ganz banales falsch.

Hier ist der Code, den ich verwende:

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

Die Ausgabe dieses Codes sieht (unter anderem) wie folgt aus:

Im Ernst, wie komme ich hierher?!
Ausnahme im Thread "main" java.lang.NoClassDefFoundError: com/planet/core360/docgen/Processor

javap -p -s java.lang.Throwable gibt mir dies:

Kompiliert aus "Throwable.java"
public class java.lang.Throwable extends java.lang.Object implements java.io.Serializable{
...
public java.lang.String getMessage();
Unterschrift: ()Ljava/lang/String;
...

8voto

Chris R Punkte 16957

Okay, es sieht also so aus, als ob mein Problem darin bestand, dass GetObjectClass verhält sich nicht so, wie man es bei einem jthrowable erwarten würde, oder zumindest sind die Ergebnisse nicht nützlich für die Zwecke der Methodenbeschaffung. Ersetzen Sie diesen Teil des Codes mit diesem funktioniert:

java_class = (*jEnv)->FindClass (jEnv, "java/lang/Throwable");
method = (*jEnv)->GetMethodID (jEnv, java_class, "getMessage", "()Ljava/lang/String;");

Das ist verdammt seltsam. Ich hoffe aber, dass dies in Zukunft jemand anderem hilft.

3voto

Chris Jester-Young Punkte 212385

Ich habe Ihren Ansatz ausprobiert, und es hat funktioniert. Ein paar Dinge jedoch: Ich verwende die C++-Schnittstelle (obwohl das keinen Unterschied machen sollte), und ich verwende Java 6 Update 10, x64 Edition, auf Ubuntu 8.04. Vielleicht macht die verwendete Java-Version und/oder Plattform einen Unterschied.

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

Ich habe die jnitest java/lang/InternalError 'Hello, world!' für meine Tests; Sie können es gerne mit anderen Ausnahmetypen versuchen!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X