2008-10-01 179 views
10

我正在用C++编写一些JNI代码,以便从Windows XP上的小程序中调用。我已经能够成功地运行applet并加载并调用JNI库,甚至可以让它调用其他DLL中的函数。我通过设置PATH系统环境变量来包含所有我的DLL所在的目录,从而得到了这个工作。UnsatisfiedLinkError:无法找到指定的程序

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

有谁知道可能是什么原因造成的?对于UnsatisifedLinkError,什么类型的东西可以给出'无法找到指定的过程'消息?

回答

14

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

举例来说,我们有一个名为input.dll的库。 DLL搜索顺序总是首先在应用程序目录中查找,并且PATH目录最后一个。在过去,我们总是从与input.dll相同的目录运行可执行文件。但是,在Windows系统目录中(DLL搜索顺序的中间)有另一个input.dll。所以当从一个java applet运行这个时,如果我将上面描述的代码包含在applet中,这会导致input.dll被加载,它会从系统目录加载input.dll。因为我们的代码期望input.dll中的某些函数不在那里(因为它是一个不同的DLL),所以加载失败时会显示有关丢失过程的错误消息。不是因为JNI函数导出错误,而是因为错误的依赖DLL被加载,并且它没有预期的函数。

+0

我有这个问题。 libA被拉到libBv2和libC中。 libBv2和libC都被找到了。问题在于libC依赖于不同的版本libBv1。 libBv1和libBv2不能一起工作。依赖walker展示了这些库,但我没有扩展libC的依赖关系。我使用procmon(http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx)来查看正在加载的库,那是当我注意到正在加载的第二版libB。 – codeDr 2014-01-28 23:11:38

0

通常,链接到其他库时,需要链接到相关的.lib文件。这听起来像你没有引用你需要的所有lib文件。检查什么不是链接,并确保将它的lib添加到链接器的列表中。

2

有一个机会,该DLL是使用C++(而不是C)构建的。除非你注意在程序上做一个外部处理,否则这是一个可能的原因。

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

+0

我在一个PE资源管理器中打开了这个DLL,并且检查了使用C链接导出了JNI函数。我也对double进行了检查,并且在DLL没有错误加载并且失败的情况下,JNI函数的签名看起来是相同的。 – matt 2008-10-07 13:13:31

0

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

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

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

+0

我正在使用标准的JNI过程。正如我所说的,在某些情况下我有它的工作。但是,当我添加这个额外的代码时,它突然停止了给定的错误。正如已经指出的那样,错误表明函数没有被导出,但我确信函数被导出。 – matt 2008-10-07 14:47:42

0

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

0

如果你已经完成了JNI手册和示例中的所有编程问题,但仍然得到相同的遗漏程序错误,问题可能出在你的路径变量上。做下面的步骤,然后再次运行:

  1. 确保你设置JAVA_HOME变量设置为JDK的文件夹(不是JRE,因为JRE犯规包含JNI头) 例子: 在环境变量设置面板定义VAR:JAVA_HOME VAL: C:\ Program Files文件\的Java \ jdk1.7.0_11
  2. 添加%JAVA_HOME%\ bin中到PATH环境变量

做这些步骤之后,你的应用程序可以找到JNI程序名称和链接JNI 。 DLL正确的方式。所以,我希望你不要再次得到这个丢失的程序错误。

相关问题