java - ¿Por qué mi código JNI no encuentra con éxito el método getMessage de jthrowable?
exception-handling (2)
De acuerdo, parece que mi problema es que GetObjectClass
no funciona de la manera que esperarías en un jwrowable, o al menos los resultados no son útiles para obtener los métodos. Reemplazar esa porción del código con esto funciona:
java_class = (*jEnv)->FindClass (jEnv, "java/lang/Throwable");
method = (*jEnv)->GetMethodID (jEnv, java_class, "getMessage", "()Ljava/lang/String;");
Damnably extraño, eso. Espero que esto ayude a alguien más en el futuro, sin embargo.
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 eso no funcionó. Obviamente estoy haciendo algo trivialmente incorrecto aquí.
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) se ve así:
En serio, ¿cómo llego aquí?
Excepción en el hilo "principal" java.lang.NoClassDefFoundError: com / planet / core360 / docgen / Processor
javap -p -s java.lang.Throwable
me da esto:
Compilado de "Throwable.java"
clase pública java.lang.Throwable extends java.lang.Object implementa java.io.Serializable {
...
public java.lang.String getMessage ();
Firma: () Ljava / lang / String;
...
Probé tu 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 mi prueba; ¡siéntete libre de probar con diferentes tipos de excepciones!