【问题标题】:Updated DLL causes JNI to throw "Exception c0000005"更新的 DLL 导致 JNI 抛出“异常 c0000005”
【发布时间】:2010-08-17 15:55:35
【问题描述】:

这是我的问题。

我有一个第三方 DLL(我没有它的源代码),我必须使用 JNI 与之通信。提供这个 DLL 的人不是 Java 公司。我在他们的 DLL 中发现了一个错误,因此编写了一些 C++ 来运行他们的 DLL,暴露了错误并将其发送给他们进行修复。我终于从他们那里得到了一个更新的 DLL,运行了我的 C++ 代码(运行良好),发现这个 bug 确实已经修复了。

但是,现在当我在我的 JNI 代码中使用这个新的 DLL 时,我会抛出以下异常;

Exception c0000005, at 1EEE3416
Access violation: attempting to read memory at address 00000004
Native function stack data: 0,3f49c0,20201,801c6,65637845,6f697470,3063206e,30303030
com.jniwrapper.FunctionExecutionException: c0000005
 at com.jniwrapper.Function.invokeCFunc(Native Method)
 at com.jniwrapper.FunctionCall.a(SourceFile:127)
 at com.jniwrapper.FunctionCall.call(SourceFile:35)
 at com.jniwrapper.Function.invoke(SourceFile:188)
 at com.tme.techdoc3.diagnostic.api.denso.DensoApiInvoker.invoke(DensoApiInvoker.java:78)
 at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.invoke(NewDensoApi.java:106)
 at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.connect(NewDensoApi.java:46)
 at ConsoleApiRunner.main(ConsoleApiRunner.java:59)

我实际上是在使用 JNIWrapper 来提供我的 JNI 代码,因此为了排除他们的产品引起的问题,我编写了自己的 JNI 代码;但我仍然遇到同样的错误。这让我确信问题出在第三方 DLL 中。

我从我在 DLL 上调用的第一个函数中得到了这个异常(顺便说一下,这个函数中没有错误......)。

我们获得 DLL 的地方已经明确表示他们不支持在 JNI 环境中使用它,即使他们不会向我发送任何类型的发行说明或固定和非固定之间的更改列表DLL。

在政治上,我对此无能为力。实际上,我仅限于 DLL 的这个供应商。

谁能想到为什么这个 DLL 在从 C++ 调用时可以工作,但在 JNI 中调用时不能工作?我一直在使用 JNI 堆栈大小 (-Xss) 和其他一些 JVM 参数,但我要么还没有找到正确的设置,要么我看错了。

非常感谢任何想法。

非常感谢。

编辑:添加我自己的 JNI 代码,看看是否有人能发现错误。

编辑 2:更正了代码复制粘贴错误。

当我使用自己的 JNI 代码时,这里是我正在使用的 .cpp 文件的实现;

#include "stdafx.h"
#include "windows.h"
#include "MyJniApi.h"
#include "ThirdParty.h"
#pragma comment(lib, "ThirdParty.lib");

ThirdPartyThing* thirdParty;

JNIEXPORT jlong JNICALL Java_com_mycompany_jni_MyJniApi_connect(JNIEnv *, jobject) {
    long connId = 0L;
    thirdParty = new ThirdPartyThing();
    long retval = thirdParty->GetConnection(&connId);
    if(0 == retval) {
        return connId;
    } else {
        return retval;
    }   
}

如您所见,它非常简单,当我将指针等弄混时,我看不到那里的任何地方。 (免责声明:这几乎是我 C++ 技能的总和!)

【问题讨论】:

    标签: java java-native-interface


    【解决方案1】:

    c0000005 表示“访问冲突”,这通常意味着使用了一个持有无效内存地址的指针。这可能只是一个错误的指针值,例如未初始化或可能表明该对象已被销毁。

    我会看两件事:

    1. 您传递的参数尤其是任何输出类型。我没有直接使用JNI,但我想如果一个变量是只读的而不是可以写入的,它可能会以不同的方式桥接到C++。如果 DLL API 期望它们已经分配,​​请确保您传递的任何缓冲区都已分配。

    2. 调用方法或作为参数传递的对象的生命周期。确保在调用 C++ 期间未收集您正在使用的 Java 对象。

    【讨论】:

    • 是的,坏指针是我在网上看到的。问题是我无法将这个事实融入我所看到的代码中。就像我说的,直接从 C++ 调用这个 DLL 工作正常,这意味着 DLL 本身是好的,不是吗?所以你是对的,问题一定出在 JNI 代码中。但是,使用这个 JNIWrapper 产品并将旧版本的 DLL 换回工作正常,但是一旦我换到新版本,我就会收到这个错误 - 这意味着问题出在 DLL 中?
    • 新的 DLL 可能工作正常,但性能或内存配置文件略有不同。这足以暴露您的 java/jni 代码中以前隐藏的错误。您可以尝试在 C++ 中引发失败,以让您了解在哪里查找。
    • 是的,你是对的。可悲的是,这是一个复制粘贴错误,而不是其他任何错误。我有很多 C++ 代码可以毫无问题地使用第三方 DLL,我可能会尝试再次点击它并尝试让它失败。
    【解决方案2】:

    我的建议是基于这个假设 - 如果你可以让它在 C++ 中运行,那么你应该能够让它在 JNI 中运行。

    我已经很久没有使用JNI了,但是像这样的问题通常是由最简单的事情引起的。

    我要非常彻底地检查的是,您正在使用新 DLL 附带的所有更新的 .h 头文件/.lib 等文件。在检查您是否指向所有新文件、正确的路径(包括您当前的 JRE)之后,重新生成您的 JNI 定义对象。搜索整个文件系统并删除旧 DLL 的任何先前版本及其依赖项/headers/libs/.obj 等。一个过时的文件可能会导致问题。

    我曾经在一个问题上浪费了三天时间,因为某些应用程序将核心 Windows DLL 的副本放在它自己的程序目录中(然后添加到 PATH),这在尝试加载正确的程序目录时造成了混乱。

    顺便说一句:DLL 是否有任何奇怪的身份验证/许可行为?还是需要加载其他无法解析的依赖?

    【讨论】:

    • 刚刚挖出了我最后一个 jni 对象。它有:#ifdef __cplusplus extern "C" { #endif ....all the function defns #ifdef __cplusplus } #endif 我隐约记得用 C++ 和 C 编写的 DLL 有问题。生成的代码可能可以追溯到 Java 1.4 如果你非常绝望地编写自己的DLL来调用他们的DLL,然后将您的Java代码连接到您的DLL。然后通过转储所有函数的参数进行调试
    【解决方案3】:

    好的,这已经解决(而不是解决)。

    最近我意识到我在此过程中引入了一条红鲱鱼。当我写自己的JNI代码(排除JNIWrapper产品引起问题)并宣布仍然抛出异常时,我一定是陷入了DLL Hell的圈子之一。当我第一次通过自己的JNI代码引入时,抛出了异常,但是在随后的日子里,重新运行我自己的JNI代码并没有抛出异常。所以我想我一定有一个旧的 DLL 在某个地方放置,导致一些错误的结果。

    所以新信息:与 JNIWrapper 一起使用时会引发异常,而不是与本土 JNI 代码一起使用。

    所以现在我更深入地研究了 JNIWrapper。在他们的一个支持论坛帖子中,它说 JNI 包装器不是为 C++ DLL 设计的,即它只支持 C++ 语言功能的子集。虚拟方法是一个特别的缺陷。由于我的第三方 DLL 是 C++ 的,我认为在以前的版本中他们使用的不是 JNIWrapper 不支持的语言功能,但现在它们是。对我来说,这意味着我不能再使用 JNIWrapper 工具了。

    相反,我使用 Swig 来生成我需要的所有 JNI 代码。无论如何,Swig 看起来还是 JNIWrapper 更好的选择,因为生成的 Java 代码更干净。

    感谢所有提出建议的人。我认为每个答案至少有一个方面是正确且有帮助的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-06
      • 1970-01-01
      • 2019-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 2010-09-14
      • 2013-03-25
      相关资源
      最近更新 更多