JNIコードがjthrowableのgetMessageメソッドを見つけられないのはなぜですか?
-
03-07-2019 - |
質問
クラスが見つからないときに生成された例外を処理しながら、jthrowableのメッセージにアクセスしようとしています。ただし、jthrowableオブジェクトのgetMessage()のメッセージIDにアクセスできず、その理由がわかりません。 getMessageの署名を"()Ljava / lang / String"に変更しようとしました。 (最後にセミコロンなしで、しかしそれは必要ですよね?)喜びなく。私はこれについて地獄のように混乱しています。 getMessageをtoStringに置き換えようとしましたが、それは機能しませんでした。明らかに私はここで些細な間違いをしています。
使用しているコードは次のとおりです。
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;
}
このコードの出力は、(とりわけ)次のようになります:
まじめな話、どうやってここに来るの?!
スレッド" main"の例外java.lang.NoClassDefFoundError:com / planet / core360 / docgen / Processor
javap -p -s java.lang.Throwable
はこれを私に与えます:
" Throwable.java"からコンパイル
パブリッククラスjava.lang.Throwableはjava.lang.Objectを拡張し、java.io.Serializable {
を実装します ...
public java.lang.String getMessage();
署名:()Ljava / lang / String;
...
解決
さて、私の問題は、 GetObjectClass
がjthrowableで期待するように動作しないか、少なくともその結果が目的には役に立たないということでしたメソッドの取得。コードのその部分をこれで置き換える:
java_class = (*jEnv)->FindClass (jEnv, "java/lang/Throwable");
method = (*jEnv)->GetMethodID (jEnv, java_class, "getMessage", "()Ljava/lang/String;");
おかしなことに、あれ。しかし、これが将来誰かに役立つことを願っています。
他のヒント
私はあなたのアプローチを試みましたが、私にとってはうまくいきました。ただし、C ++インターフェースを使用しています(違いはありませんが)。Ubuntu8.04では、Java 6アップデート10、x64エディションを使用しています。おそらく、使用されているJavaバージョンやプラットフォームによって違いが生じるでしょう。
#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();
}
テストには jnitest java / lang / InternalError 'Hello、world!'
を使用しました。さまざまな例外タイプを試してみてください!