Java UnsatisfiedLinkError: 找不到指定的程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/159846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 09:53:54  来源:igfitidea点击:

UnsatisfiedLinkError: The specified procedure could not be found

javajava-native-interface

提问by matt

I'm writing some JNI code in C++ to be called from an applet on Windows XP. I've been able to successfully run the applet and have the JNI library loaded and called, even going so far as having it call functions in other DLLs. I got this working by setting up the PATH system environment variable to include the directory all of my DLLs are in.

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

So, the problem, is that I add another call that uses a new external DLL, and suddenly when loading the library, an UnsatisfiedLinkError is thrown. The message is: 'The specified procedure could not be found'. This doesn't seem to be a problem with a missing dependent DLL, because I can remove a dependent DLL and get a different message about dependent DLL missing. From what I've been able to find online, it appears that this message means that a native Java function implementation is missing from the DLL, but it's odd that it works fine without this extra bit of code.

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

Does anyone know what might be causing this? What kinds of things can give a 'The specified procedure could not be found' messages for an UnsatisifedLinkError?

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

采纳答案by matt

I figured out the problem. This was a doozy. The message "The specified procedure could not be found" for UnsatisfiedLinkError indicates that a function in the root dll or in a dependent dllcould not be found. The most likely cause of this in a JNI situation is that the native JNI function is not exported correctly. But this can apparently happen if a dependent DLL is loaded and that DLL is missing a function required by its parent.

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

By way of example, we have a library named input.dll. The DLL search order is to always look in the application directory first and the PATH directories last. In the past, we always ran executables from the same directory as input.dll. However, there is another input.dll in the windows system directory (which is in the middle of the DLL search order). So when running this from a java applet, if I include the code described above in the applet, which causes input.dll to be loaded, it loads the input.dll from the system directory. Because our code is expecting certain functions in input.dll which aren't there (because it's a different DLL) the load fails with an error message about missing procedures. Not because the JNI functions are exported wrong, but because the wrong dependent DLL was loaded and it didn't have the expected functions in it.

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

回答by Jeff Yates

Usually, when linking to other libraries, you need to link to the relevant .lib file. It sounds like you aren't referencing all the lib files you need. Check what isn't linking and make sure you add it's lib to the list for the linker.

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

回答by anjanb

There is a chance that the DLL was built using C++(as opposed to C). unless you took care to do an extern on the procedure,this is one possible reason.

DLL 有可能是使用 C++(而不是 C)构建的。除非您小心地对程序进行外部检查,否则这是一个可能的原因。

Try exporting all the functions from the DLL. If the list includes your function, then you're good.

尝试从 DLL 中导出所有函数。如果列表包括您的功能,那么您很好。

回答by Anthony Cramp

Did you create the new external DLL using the standard JNI procedure? I.e., using javah and so forth? If so, then I am not sure what is wrong.

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

If not, then the procedure you're trying to call hasn't been exported (as mentioned by anjanb). I am aware of two way of exporting functions: a separate export list and marking specific functions with __declspec(dllexport).

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

Can't access variable in C++ DLL from a C apphas a little more information the topic of DLLs.

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

回答by Mike

Compile your c++ code in debug mode. Then insert the DebugBreak(); statement where you would like to start debugging. Run the java code. When the DebugBreak() statement is encountered you will get a popup with a Debug button on it. Click on it. Dev Studio will open with your program in machine code. Step over with the debugger twice and you should be able to step over your source code.

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

回答by Mustafa Kemal

If you have done all programming issue at JNI manuals and examples but still you are getting same missing procedure error, problem can be at your path variable probably. Do below steps and run again:

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

  1. Be sure about you set JAVA_HOME variable to your JDK folder(not JRE because JRE doesnt contain jni header) Example: At environment variable settings panel define var:JAVA_HOME val:C:\Program Files\Java\jdk1.7.0_11
  2. add %JAVA_HOME%\binto your path variable
  1. 确保将 JAVA_HOME 变量设置为 JDK 文件夹(不是 JRE,因为 JRE 不包含 jni 头文件)示例: 在环境变量设置面板中定义 var:JAVA_HOME val:C:\Program Files\Java\jdk1.7.0_11
  2. %JAVA_HOME%\bin添加到您的路径变量中

After doing those steps, your application can find jni procedure name and links to JNI.dll in right way. So, i hope you dont get this missing procedure error again.

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