开发者社区> 问答> 正文

通过JNI NewObject创建实例时jvm.dll中的异常0xC0000005

我正在为现有应用程序编写插件。实现语言是C。但是,实际功能是用Java实现的。出于这个原因,我使用Java本机接口(JNI)从C中创建JVM实例。我可以找到合适的Java类并创建一个实例。代码如下所示:

login(uintptr_t connection, const char* username, …) {
    …
    jmethodID constructor = (*env)->GetMethodID(env, ps->class, "<init>", "(JLjava/lang/String;)V");
    jstring jusername = (*env)->NewStringUTF(env, username);
    jobject instance = (*env)->NewObject(env, ps->class, constructor, connection, jusername);

一切正常。

在Linux上。

在Windows上,这完全是一团糟。一旦我尝试创建Java类的实例,就会抛出一个

EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0813751f, pid=8, tid=0x00000009

更多详细信息将写入日志文件,但是堆栈跟踪除了指向jvm.dll中的某处外没有帮助。单步调试器并不是很有见地。请注意,此问题此不同

问题来源:Stack Overflow

展开
收起
montos 2020-03-25 19:17:19 659 0
1 条回答
写回答
取消 提交回答
  • 几天后,我发现了。

    我正在调用的构造函数需要一个参数。类型是long(Java)aka J(JNI类型签名)aka jlong(对应的C类型)。AC uintptr_t与兼容jlong。

    在Linux上,我uintptr_t是8字节长,因为我处于具有64位应用程序的amd64环境中。对于Windows,该应用程序以32位构建。结果uintptr_t只有4个字节长,但是JVM仍然希望有8个字节jlong。但是,NewObject它是可变参数功能,不会自动升级并且不能保证类型安全。

    login(uintptr_t connection, const char* username, …) {
        …
        jmethodID constructor = (*env)->GetMethodID(env, ps->class, "<init>", "(JLjava/lang/String;)V");
        jstring jusername = (*env)->NewStringUTF(env, username);
        jlong jconnection = connection;
        jobject instance = (*env)->NewObject(env, ps->class, constructor, jconnection, jusername);
    

    一个简单的类型转换为正确的类型就是解决方案。我希望这个陷阱也存在于文档中CallVoidMethod或其中Call*Method 提到的任何一个。

    回答来源:Stack Overflow

    2020-03-25 19:18:17
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
JVM实战 立即下载
JVM的GC 立即下载
基于JVM的脚本语言开发、运用实践 立即下载