Вопрос

Я пытаюсь получить доступ к сообщению в jthrowable, обрабатывая исключение, сгенерированное, когда мне не удается найти класс. Однако я не могу получить доступ к идентификатору сообщения getMessage () для объекта jthrowable, и я не знаю почему. Я попытался изменить подпись 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 ++ (хотя это не должно иметь никакого значения), и я использую Java 6 update 10, x64 edition, в Ubuntu 8.04. Возможно, используемая версия 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!' для моего тестирования; не стесняйтесь пробовать разные типы исключений!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top