Why can't I find the jthrowable getMessage method in my JNI code?

I am trying to access a message in jthrowable by throwing an generated exception when I cannot find the class. However, I cannot access the getMessage () message id on the jthrowable object, and I don't know why. I tried changing the signature of getMessage to "() Ljava / lang / String" (without a semicolon at the end, but this is necessary, right?) Without joy. I am confused about this. I even tried replacing getMessage with toString, and that didn't work. Obviously, I'm doing something trilogically wrong here.

Here is the code I'm using:

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

The result of this code (by the way) is as follows:

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

javap -p -s java.lang.Throwable gives me the following:

Composed 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; ...

+7
java exception-handling jni
source share
2 answers

So it looks like my problem was that GetObjectClass not acting as you expected on jthrowable, or at least the results of this are not useful for the purpose of getting methods. Replacing this part of the code with this works:

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

Truly strange that. Hope this helps someone else in the future.

+8
source share

I tried your approach and it worked for me. A few things: I use the C ++ interface (although this should not change), and I use the update version for Java 6 version 10, x64 on Ubuntu 8.04. Perhaps the version of Java you are using and / or the platform will matter.

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

I used jnitest java/lang/InternalError 'Hello, world!' for my testing; Feel free to use different types of exceptions!

+3
source share

All Articles