【问题标题】:How do I get an error message when failing to load a JVM via JNI?无法通过 JNI 加载 JVM 时如何收到错误消息?
【发布时间】:2009-04-28 16:50:08
【问题描述】:

我想检索解释 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++ 编码,所以如果有人可以展示一种将错误捕获到字符串流中的方法,那将是理想的。

谢谢, 兰迪

【问题讨论】:

    标签: java c++ jvm java-native-interface jvm-arguments


    【解决方案1】:

    我能够通过使用此处描述的“vfprintf”选项获得所需的内容:

    https://web.archive.org/web/20111229234347/http://java.sun.com/products/jdk/faq/jnifaq-old.html

    虽然我使用了 jdk1.2 选项。这段代码 sn -p 总结了我的解决方案:

    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();
    

    另外有趣的是,我一生都无法使用任何 freopen 或 dup2 技巧正确捕获 stdout 或 stderr。我可以加载我的 own dll 并正确重定向,但不能正确重定向 jvm。无论如何,这种方式更好,因为我希望错误在内存中而不是在文件中。

    【讨论】:

    • sun.java.com 的链接不再有效,并且函数setError() 未在 sn-p 中声明。关于在哪里可以找到它的任何提示?
    • 这似乎是同一个链接,虽然已经很久了:old-faq。 setError 方法只是我们定义的一个辅助方法。 jniErrors 字符串将包含该点的错误消息。
    • 感谢您的指点。我应该更新答案中的链接吗?
    【解决方案2】:

    当我编写这段代码时,我也会通过 stdout/stderr 得到错误。

    在您的进程中重定向 stdout/stderr 的最佳方法是使用 freopen。这是专门针对该主题的StackOverflow question

    但是,一旦调用通过,您将获得一个JNIEnv,并且所有进一步的错误检查都可以并且应该通过调用JNIEnv::ExceptionOccurred() 来完成,这可能会返回一个Throwable 对象,然后您可以查询该对象使用您的 JNI 代码。

    【讨论】:

      【解决方案3】:

      在获得标准输出和标准错误(无论如何您都需要)之后,将 -Xcheck:jni 添加到您的 jvm 命令行以从 jvm 获取额外的与 jni 相关的警告。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-13
        • 2013-07-20
        • 1970-01-01
        • 2021-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-28
        相关资源
        最近更新 更多