为什么这个基于 JNI 的 JBoss 模块会抛出错误"找不到依赖库"?



我有一个Java web应用程序myproject.war部署到JBoss。应用程序的一部分使用JNI连接到c++ DLL,该DLL从一组第三方库调用函数。我们正在将这个应用程序从x32服务器迁移到x64服务器。

优先环境构建

    32位Windows Server 2003
  • JBoss 6。X
  • Java 1.6.X

新建环境

  • 64位Windows Server 2008 R2, SP1 (6.1.7601)
  • JBoss AS 7.2.0 Final "Janus"
  • Java Runtime 1.7.0_45-b18.
  • Visual Studio 2010 Redistributable x64已安装

在旧系统上,自定义DLL和第三方库被随意地转储到C:WindowsSystem32中,并且应用程序能够通过JNI成功地连接到它们。第三方库包括几个dll、一些ICC配置文件和一个Resource文件夹,其中包含包含True-type字体、配置和其他文件的子文件夹。

对于迁移,创建了一个JBoss模块来包含JNI代码。将Java/JNI代码移至MyModule.jar,将MyDriver.dll重新编译为x64。获取X64版本的第三方库。

我有

  • 使用Visual Studio 2010 (10.0.40219.1 SP1Rel)重新编译64位MyDriver.dll
  • MyDriver.dll和64位版本的第三方dll和资源文件夹放入模块文件夹..mainlibwin-x86_64
  • 将模块文件复制到modules文件夹
  • 下的路径
  • module.xml创建
    • 与适当的资源MyModule.jar
      • MyDriverLoader加载MyDriver.dll
    • 参考模块sun.jdk,我不是100%确定JNI需要。

使用

编译DLL
  • MFC的使用:使用标准Windows库

无论我做什么,在启动应用程序时,JBoss都会抛出以下Java错误:

. lang。UnsatisfiedLinkError: D:Jboss Jboss -7.2.0. final modulescommymodulemainlibwin-x86_64MyDriver.dll: Can't find dependent libraries

这告诉我的是

    JBoss可以从模块中检测正确的DLL,因此我已经正确配置了模块。
  1. 某个依赖库不在JBoss的路径中。

我尝试了以下解决方案,但都不起作用,错误仍然存在:

  1. 我已经安装了Visual Studio 2010 Redistributable x64,它可能已经打包在里面了。
  2. 我已经明确地将{JBOSS_HOME}modulescommymodulemainlibwin-x86_64添加到Windows环境变量PATH中,并与echo %PATH%确认这一点,其中包括:D:Javajdk1.7.0_45bin;D:Jbossjboss-7.2.0.Finalmodulescommymodulemainlibwin-x86_64;
  3. 我已经运行了x64 Dependency Walker,它告诉我没有找到MSVCP100D.DLL, MSVCR100D.DLLIESHIMS.DLL。我在c:WindowsSystem32C:WindowsSysWOW64文件夹中都找到了MSCV*.DLL文件,但是它们的文件大小不同。依赖沃克已经检测到其他文件的路径驻留在system32,所以我不明白为什么它没有找到MSCV*.DLL文件。为了测试,我将它们放入与MyDriver.dll相同的文件夹...libwin-x86_64中,但这没有改变任何东西。

我能做些什么来解决这个问题?

module.xml

<module xmlns="urn:jboss:module:1.1" name="com.mymodule">
    <main-class name="com.mymodule.DriverClassName"/>
    <resources>
        <resource-root path="MyModule.jar"/>
    </resources>
    <dependencies>
        <module name="sun.jdk"/>
    </dependencies>    
</module>

MyDriverLoader.java

public class MyDriverLoader {
/**
 * Load C++ Library
 */
static {  
    System.loadLibrary("MyDriver");
}
/**
 * Native Method to return the version of the C++ DLL.
 */
public native static String getVersion();
/**
 * Main method calls getVersion.
 * 
 * @param args
 */
public static void main(String args[]) {
    System.out.println("MyDriverLoader calling MyDriver.dll version " + getVersion());
}
}

jboss-deployment-structure

<jboss-deployment-structure>
    <deployment>    
    <dependencies>
            <module name="com.mymodule" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>
模块mymodule的文件夹结构

{JBOSS_HOME} com mymodule里 模块主要

  • MyModule.jar
    • 包含
    • lib win-x86_64
    • MyDriver.dll
    • ThirdPartyA.dll
    • ThirdPartyB.dll
    • ThirdPartyC.dll
    • ThirdPartyD.dll
    • 环境 数据资源
      • foo.optionfile
      • bar.optionfile

我想出来了,方法如下。

  1. 我首先将DLL从JBoss中取出,并尝试通过x64 dev/qa服务器上的JNI调用本机方法直接访问它。这失败了,出现了同样的错误。

  2. 我从DLL中剥离了对第三方库的引用,并试图再次访问它。这也以同样的错误失败了。这意味着不是第三方库或它们的路径问题。

  3. 我创建了一个普通的DLL,它什么也不做,只是吐出一个字符串,并试图以与前两次相同的方式访问它。它也失败了。

  4. 我一直在编译vs2010中的DLL作为调试。我将DLL重新编译为Release。

我找到了一个很有帮助的答案,我再也找不到了,否则我会把它链接起来。

正如我现在所理解的,如果你在调试中编译一个DLL,它不应该是可重新分发的。我在Debug中编译并在x32开发服务器上使用的x32 DLL不是这种情况,但编译后的x64 DLL肯定是这种情况。我将其编译为Release,并能够在整个应用程序中使用DLL。

我已经更改了构建未来开发可部署的例程。

相关内容

最新更新