Как получить сообщение об ошибке при сбое загрузки JVM через JNI? - PullRequest
3 голосов
/ 28 апреля 2009

Я хотел бы получить сообщение об ошибке, объясняющее, почему JVM не удалось загрузить. Из приведенных здесь примеров:

http://java.sun.com/docs/books/jni/html/invoke.html

Я извлек этот пример:

 /* Create the Java VM */
 res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

 if (res < 0) {
     // retrieve verbose error here?
     fprintf(stderr, "Can't create Java VM\n");
     exit(1);
 }

В моем конкретном случае я предоставляю недопустимые аргументы в vm_args и ожидаю увидеть, что я получу в командной строке: "Нераспознанная опция: -foo = bar"

При дальнейшем тестировании похоже, что jvm отправляет сообщение, которое я хочу передать в stdout или stderr. Я считаю, что мне понадобится захватить stdout и stderr, чтобы получить искомую ошибку (если, конечно, нет более простого способа). Я пишу код на C ++, так что если кто-то может показать способ записи ошибки в поток строк, это было бы идеально.

Спасибо, Randy

Ответы [ 3 ]

4 голосов
/ 29 апреля 2009

Я смог получить то, что мне было нужно, используя опцию "vfprintf", описанную здесь:

http://java.sun.com/products/jdk/faq/jnifaq-old.html

хотя я использовал опции jdk1.2. Этот фрагмент кода обобщает мое решение:

static string jniErrors;

static jint JNICALL my_vfprintf(FILE *fp, const char *format, va_list args)
{
    char buf[1024];
    vsnprintf(buf, sizeof(buf), format, args);
    jniErrors += buf;
    return 0;
}

...

JavaVMOption options[1];
options[0].optionString = "vfprintf";
options[0].extraInfo = my_vfprintf;

JavaVMInitArgs vm_args;
memset(&vm_args, 0, sizeof(vm_args));
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.version = JNI_VERSION_1_4;
vm_args.ignoreUnrecognized = JNI_FALSE;

JNIEnv env;
JavaVM jvm;

jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

if (res != JNI_OK)
    setError(jniErrors);

jniErrors.clear();

Также интересно то, что я не мог на протяжении всей жизни правильно захватывать stdout или stderr с помощью трюков freopen или dup2. Я мог бы загрузить свою собственную dll и правильно перенаправить, но не jvm. В любом случае, так лучше, потому что я хотел ошибок в памяти, а не в файле.

0 голосов
/ 29 апреля 2009

Получив stdout и stderr, которые вам все равно понадобятся, добавьте -Xcheck: jni в вашу командную строку jvm, чтобы получить дополнительные jni-связанные предупреждения от jvm.

0 голосов
/ 29 апреля 2009

Когда я писал этот код, я также получал ошибку через stdout / stderr.

Лучший способ перенаправить stdout / stderr в вашем процессе - использовать freopen . Вот StackOverflow вопрос специально об этой теме.

Однако, как только этот вызов будет принят, у вас будет JNIEnv, и вся дальнейшая проверка ошибок может и должна быть сделана путем вызова JNIEnv::ExceptionOccurred(), который может вернуть объект Throwable, который вы затем можете запросить с вашим кодом JNI.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...