2008-10-18 14 views
7

Estoy tratando de acceder al mensaje en un jwrowable mientras entrego una excepción generada cuando no puedo encontrar una clase. Sin embargo, no puedo acceder al ID de mensaje de getMessage() en el objeto jthrowable, y no sé por qué. Intenté cambiar la firma de getMessage por "() Ljava/lang/String" (sin el punto y coma al final, pero eso es necesario, ¿no?) Sin alegría. Estoy confundido como el infierno sobre esto. Incluso traté de reemplazar getMessage por toString, y que no funcionó. Obviamente estoy haciendo algo trivialmente incorrecto aquí.¿Por qué mi código JNI no encuentra con éxito el método getMessage de jthrowable?

Aquí está el código que estoy 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; 
} 

La salida de este código (entre otras cosas) tiene el siguiente aspecto:

Seriously, how do I get here?!
Exception in thread "main" java.lang.NoClassDefFoundError: com/planet/core360/docgen/Processor

javap -p -s java.lang.Throwable me da esto:

Compiled from "Throwable.java"
public class java.lang.Throwable extends java.lang.Object implements java.io.Serializable{
...
public java.lang.String getMessage();
Signature:()Ljava/lang/String;
...

Respuesta

8

De acuerdo, parece que mi problema fue que GetObjectClass no funciona de la manera en que se esperaba En un jwrowable, o al menos los resultados no son útiles para obtener los métodos. Reemplazar esa parte del código con esto funciona:

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

Muy extraño, eso. Espero que esto ayude a alguien más en el futuro, sin embargo.

+0

¡Me ayudó! :-) –

+3

¿Es posible que GetObjectClass() no funcione cuando hay una excepción activa? Pruebe '(* env) -> ExceptionClear (env)' antes de llamar a GetObjectClass. – Qwertie

3

Intenté su enfoque, y funcionó para mí. Sin embargo, algunas cosas: estoy usando la interfaz C++ (aunque eso no debería marcar la diferencia), y estoy usando Java 6 update 10, x64 edition, en Ubuntu 8.04. Tal vez la versión de Java y/o la plataforma utilizada marcarán la diferencia.

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

He usado jnitest java/lang/InternalError 'Hello, world!' para mis pruebas; ¡siéntete libre de probar con diferentes tipos de excepciones!

Cuestiones relacionadas