【问题标题】:UnsatisfiedLinkError: The specified procedure could not be foundUnsatisfiedLinkError:找不到指定的过程
【发布时间】:2008-10-01 21:28:31
【问题描述】:

我正在用 C++ 编写一些 JNI 代码,以便从 Windows XP 上的小程序中调用。我已经能够成功地运行小程序并加载和调用 JNI 库,甚至可以让它调用其他 DLL 中的函数。我通过设置 PATH 系统环境变量来包含我的所有 DLL 所在的目录来实现此功能。

所以,问题在于我添加了另一个使用新外部 DLL 的调用,并且在加载库时突然抛出 UnsatisfiedLinkError。消息是:“找不到指定的过程”。这似乎不是缺少依赖 DLL 的问题,因为我可以删除依赖 DLL 并获得有关依赖 DLL 丢失的不同消息。从我在网上找到的信息来看,这条消息似乎意味着 DLL 中缺少本机 Java 函数实现,但奇怪的是,如果没有这些额外的代码,它可以正常工作。

有谁知道这可能是什么原因造成的?对于 UnsatisifedLinkError,什么样的事情可以给出“找不到指定的过程”消息?

【问题讨论】:

    标签: java java-native-interface


    【解决方案1】:

    我发现了问题所在。这真是太棒了。 UnsatisfiedLinkError 的消息“找不到指定的过程”表示找不到根 dll 或 依赖 dll 中的函数。在 JNI 情况下,最可能的原因是未正确导出本机 JNI 函数。但是,如果加载了依赖 DLL 并且该 DLL 缺少其父级所需的函数,则显然会发生这种情况。

    例如,我们有一个名为 input.dll 的库。 DLL 搜索顺序是始终首先查找应用程序目录,最后查找 PATH 目录。过去,我们总是从与 input.dll 相同的目录中运行可执行文件。但是,windows系统目录下还有另一个input.dll(在DLL搜索顺序的中间)。因此,当从 java 小程序运行它时,如果我在小程序中包含上述代码,这会导致加载 input.dll,它会从系统目录加载 input.dll。因为我们的代码需要 input.dll 中不存在的某些函数(因为它是不同的 DLL),所以加载失败并显示有关缺少过程的错误消息。不是因为 JNI 函数导出错误,而是因为加载了错误的依赖 DLL,并且其中没有预期的函数。

    【讨论】:

    • 我遇到了这个问题。 libA 引入了 libBv2 和 libC。 libBv2 和 libC 都被找到了。问题是 libC 依赖于不同的版本 libBv1。 libBv1 和 libBv2 不能一起工作。 dependency walker 显示了这些库,但我没有扩展 libC 的依赖项。我使用 procmon (technet.microsoft.com/en-us/sysinternals/bb896645.aspx) 查看正在加载的库,这时我注意到 libB 的第二个版本正在加载。
    【解决方案2】:

    DLL 有可能是使用 C++(而不是 C)构建的。除非您注意对程序进行 extern,否则这是可能的原因之一。

    尝试从 DLL 中导出所有函数。如果列表中包含你的函数,那么你很好。

    【讨论】:

    • 我在 PE 资源管理器中打开了 DLL,并仔细检查了 JNI 函数是否使用 C 链接导出。我还仔细检查了,JNI 函数的签名在 DLL 加载无误和失败的情况下看起来是一样的。
    【解决方案3】:

    通常,在链接其他库时,需要链接到相关的.lib 文件。听起来您没有引用所需的所有 lib 文件。检查未链接的内容并确保将其库添加到链接器的列表中。

    【讨论】:

      【解决方案4】:

      您是否使用标准 JNI 过程创建了新的外部 DLL?即,使用 javah 等等?如果是这样,那么我不确定是什么问题。

      如果没有,那么您尝试调用的过程尚未导出(如 anjanb 所述)。我知道导出函数的两种方式:单独的导出列表和使用 __declspec(dllexport) 标记特定函数。

      Can't access variable in C++ DLL from a C app 有更多关于 DLL 主题的信息。

      【讨论】:

      • 我正在使用标准的 JNI 程序。正如我所说,我在某些情况下可以使用它。但是当我添加这个额外的代码时,它突然停止处理给定的错误。正如已经指出的那样,错误表明该函数未导出,但我很肯定这些函数已导出。
      【解决方案5】:

      在调试模式下编译您的 c++ 代码。然后插入 DebugBreak();您要开始调试的语句。运行java代码。当遇到 DebugBreak() 语句时,您将看到一个带有 Debug 按钮的弹出窗口。点击它。 Dev Studio 将以机器代码打开您的程序。使用调试器单步执行两次,您应该能够单步执行您的源代码。

      【讨论】:

        【解决方案6】:

        如果您在 JNI 手册和示例中完成了所有编程问题,但仍然遇到相同的缺失程序错误,则问题可能出在您的路径变量上。执行以下步骤并再次运行:

        1. 确保将 JAVA_HOME 变量设置为 JDK 文件夹(不是 JRE,因为 JRE 不包含 jni 标头) 例子: 在环境变量设置面板中定义 var:JAVA_HOME val:C:\Program Files\Java\jdk1.7.0_11
        2. %JAVA_HOME%\bin 添加到您的路径变量中

        完成这些步骤后,您的应用程序可以找到 jni 过程名称并以正确的方式链接到 JNI.dll。所以,我希望你不要再遇到这个丢失的程序错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-04-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-04-16
          相关资源
          最近更新 更多