Pergunta

Estou tentando acessar a mensagem em uma entrega enquanto jthrowable uma exceção gerada quando eu deixar de encontrar uma classe. No entanto, eu sou incapaz de acessar o ID da mensagem de getMessage () no objeto jthrowable, e eu não sei porquê. Eu tentei mudar a assinatura de getMessage para "() Ljava / lang / String" (sem o ponto e vírgula no final, mas isso é necessário, certo?), Sem alegria. Estou confuso como o inferno sobre isso. Eu até tentei substituir getMessage com toString, e que não funcionou. Obviamente eu estou fazendo algo trivialmente errada aqui.

Aqui está o código que estou usando:

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

A saída desse código (entre outras coisas) se parece com isso:

A sério, como faço para chegar aqui ?!
Exception in thread "main" java.lang.NoClassDefFoundError: com / planeta / core360 / docgen / Processador

javap -p -s java.lang.Throwable me dá esta:

Compilado de
"Throwable.java" classe pública java.lang.Throwable estende implementos java.lang.Object java.io.Serializable {
...
pública java.lang.String getMessage ();
Assinatura: () Ljava / lang / String;
...

Foi útil?

Solução

Ok, então parece que o meu problema era que GetObjectClass não age da maneira que você esperaria que em um jthrowable, ou pelo menos os resultados não são úteis para efeitos de obtenção de métodos. Substituir a parte do código com isso funciona:

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

terrivelmente estranho, isso. Espero que isso ajude alguém no futuro, no entanto.

Outras dicas

Eu tentei a sua abordagem, e funcionou para mim. Algumas coisas, porém: eu estou usando a interface C ++ (embora isso não deve fazer a diferença), e eu estou usando Java 6 Update 10, edição x64, no Ubuntu 8.04. Talvez a versão e / ou plataforma Java usado vai fazer a diferença.

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

Eu tenho jnitest java/lang/InternalError 'Hello, world!' utilizado para o meu teste; sentir-se livre para experimentar com diferentes tipos de exceção!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top