【问题标题】:Why does my JNI code not successfully find a jthrowable's getMessage method?为什么我的 JNI 代码没有成功找到 jthrowable 的 getMessage 方法?
【发布时间】:2008-10-18 22:09:22
【问题描述】:

我正在尝试访问 jthrowable 中的消息,同时处理我找不到类时生成的异常。但是,我无法访问 jthrowable 对象上 getMessage() 的消息 ID,我不知道为什么。我尝试将 getMessage 的签名更改为“()Ljava/lang/String”(最后没有分号,但这是必要的,对吧?)没有喜悦。我对此感到困惑。我什至尝试用 toString 替换 getMessage,而 that 没有用。很明显,我在这里做错了什么。

这是我正在使用的代码:

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{
...
公共 java.lang.String getMessage();
签名:()Ljava/lang/String;
...

【问题讨论】:

    标签: java exception-handling java-native-interface


    【解决方案1】:

    好的,所以看起来我的问题是 GetObjectClass 在 jthrowable 上的行为方式与您期望的不同,或者至少它的结果对于获取方法没有用处。用这个替换那部分代码:

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

    这真是太奇怪了。不过,我希望这对其他人有所帮助。

    【讨论】:

    • 当异常处于活动状态时,GetObjectClass() 是否可能不起作用?在调用 GetObjectClass 之前尝试 (*env)->ExceptionClear(env)
    【解决方案2】:

    我尝试了你的方法,它对我有用。不过有几件事:我正在使用 C++ 接口(尽管这不应该有所作为),并且我在 Ubuntu 8.04 上使用 Java 6 update 10, x64 edition。也许使用的 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!' 进行测试;随意尝试不同的异常类型!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-24
      • 2020-06-08
      • 2021-10-13
      • 2022-01-09
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多