I would like to retrieve an error message that explains why the jvm failed to load. From the examples provided here:
我想检索一条错误消息,解释为什么jvm无法加载。从这里提供的示例:
http://java.sun.com/docs/books/jni/html/invoke.html
I extracted this example:
我提取了这个例子:
/* 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);
}
In my specific case I'm providing invalid arguments in the vm_args and would expect to see what I get on the command line: "Unrecognized option: -foo=bar"
在我的具体情况下,我在vm_args中提供了无效的参数,并希望看到我在命令行上看到的内容:“无法识别的选项:-foo = bar”
On further testing it looks like the jvm is putting the message I want to stdout or stderr. I believe I would need to capture stdout and stderr to get the error I'm looking for (unless of course there is a simpler way). I'm coding in C++ so if someone can show a way to capture the error into a stringstream that would be ideal.
在进一步测试时,看起来jvm正在将我想要的消息放入stdout或stderr。我相信我需要捕获stdout和stderr来获取我正在寻找的错误(除非当然有一种更简单的方法)。我正在使用C ++进行编码,因此如果有人能够展示将错误捕获到字符串流中的方法,那将是理想的。
Thanks, Randy
3 个解决方案
#1
I was able to get what I needed by using the "vfprintf" option described here:
通过使用此处描述的“vfprintf”选项,我能够获得所需的内容:
http://java.sun.com/products/jdk/faq/jnifaq-old.html
although I used the jdk1.2 options. This code snippet summarizes my solution:
虽然我使用了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();
Also interesting was that I could not for the life of me capture stdout or stderr correctly with any of the freopen or dup2 tricks. I could load my own dll and redirect correctly but not the jvm. Anyway, it's better this way because I wanted the errors in memory rather than in a file.
同样有趣的是,我无法在生活中使用任何freopen或dup2技巧正确捕获stdout或stderr。我可以加载我自己的DLL并正确重定向但不是jvm。无论如何,这种方式更好,因为我想要内存中的错误而不是文件中的错误。
#2
When I wrote this code I would also get the error via stdout/stderr.
当我编写这段代码时,我也会通过stdout / stderr得到错误。
The best way to redirect stdout/stderr in your process is by using freopen. Here is a * question specifically about that subject.
在您的进程中重定向stdout / stderr的最佳方法是使用freopen。这是一个*问题,专门针对该主题。
However, once that call is passed, you will then have a JNIEnv
, and all further error checking can and should be done by calling JNIEnv::ExceptionOccurred()
, which will may return a Throwable
object that you can then interrogate with your JNI code.
但是,一旦调用通过,您将拥有一个JNIEnv,并且所有进一步的错误检查都可以而且应该通过调用JNIEnv :: ExceptionOccurred()完成,这可能会返回一个Throwable对象,然后您可以使用您的JNI代码查询。
#3
After getting a hold of stdout and stderr, which you'll need anyway, add -Xcheck:jni to your jvm command line to get extra jni-related warnings from the jvm.
在获得stdout和stderr之后,无论如何都需要将-Xcheck:jni添加到你的jvm命令行以从jvm获取额外的jni相关警告。
#1
I was able to get what I needed by using the "vfprintf" option described here:
通过使用此处描述的“vfprintf”选项,我能够获得所需的内容:
http://java.sun.com/products/jdk/faq/jnifaq-old.html
although I used the jdk1.2 options. This code snippet summarizes my solution:
虽然我使用了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();
Also interesting was that I could not for the life of me capture stdout or stderr correctly with any of the freopen or dup2 tricks. I could load my own dll and redirect correctly but not the jvm. Anyway, it's better this way because I wanted the errors in memory rather than in a file.
同样有趣的是,我无法在生活中使用任何freopen或dup2技巧正确捕获stdout或stderr。我可以加载我自己的DLL并正确重定向但不是jvm。无论如何,这种方式更好,因为我想要内存中的错误而不是文件中的错误。
#2
When I wrote this code I would also get the error via stdout/stderr.
当我编写这段代码时,我也会通过stdout / stderr得到错误。
The best way to redirect stdout/stderr in your process is by using freopen. Here is a * question specifically about that subject.
在您的进程中重定向stdout / stderr的最佳方法是使用freopen。这是一个*问题,专门针对该主题。
However, once that call is passed, you will then have a JNIEnv
, and all further error checking can and should be done by calling JNIEnv::ExceptionOccurred()
, which will may return a Throwable
object that you can then interrogate with your JNI code.
但是,一旦调用通过,您将拥有一个JNIEnv,并且所有进一步的错误检查都可以而且应该通过调用JNIEnv :: ExceptionOccurred()完成,这可能会返回一个Throwable对象,然后您可以使用您的JNI代码查询。
#3
After getting a hold of stdout and stderr, which you'll need anyway, add -Xcheck:jni to your jvm command line to get extra jni-related warnings from the jvm.
在获得stdout和stderr之后,无论如何都需要将-Xcheck:jni添加到你的jvm命令行以从jvm获取额外的jni相关警告。