Java 为什么这个基于JNI的JBoss模块会抛出错误;Can';“找不到依赖库”吗;?

Java 为什么这个基于JNI的JBoss模块会抛出错误;Can';“找不到依赖库”吗;?,java,c++,java-native-interface,jboss7.x,jboss-modules,Java,C++,Java Native Interface,Jboss7.x,Jboss Modules,我在JBoss上部署了一个Java web应用程序myproject.war。应用程序的一部分使用JNI连接到C++ DLL,该调用从一组第三方库调用函数。我们正在将此应用程序从x32服务器迁移到x64服务器 优先环境构建 32位Windows Server 2003 JBoss6.X Java1.6.X 新环境建设 64位Windows Server 2008 R2,SP1(6.1.7601) JBoss AS 7.2.0最终版“Janus” Java运行时1.7.0_45-b18 已安

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

优先环境构建

  • 32位Windows Server 2003
  • JBoss6.X
  • Java1.6.X
新环境建设

  • 64位Windows Server 2008 R2,SP1(6.1.7601)
  • JBoss AS 7.2.0最终版“Janus”
  • Java运行时1.7.0_45-b18
  • 已安装Visual Studio 2010可再发行x64
在旧系统上,自定义DLL和第三方库被随意转储到
C:\Windows\System32\
中,应用程序能够通过JNI成功连接到它们。第三方库包括几个DLL、一些ICC配置文件和一个资源文件夹,其中包含文件的子文件夹,包括True type字体、配置和其他文件

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

我有

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

  • MFC的使用:使用标准Windows库
无论我做什么,在启动应用程序时,JBoss都会抛出以下Java错误:

java.lang.unsatifiedlinkerror:D:\Jboss\Jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86\u 64\MyDriver.dll:找不到依赖库

这告诉我的是

  • JBoss可以从模块中检测到正确的DLL,因此我已经正确配置了模块
  • 某些依赖库不在JBoss的路径中
  • 我尝试了以下解决方案,但均无效,错误依然存在:

  • 我已经安装了VisualStudio2010可再发行x64,它可能已经打包好了
  • 我已经明确地将
    {JBOSS\u HOME}\modules\com\mymodule\main\lib\win-x86\u 64
    添加到Windows环境变量
    PATH
    ,并用
    echo%PATH%
    确认了这一点,其中包括:
    D:\Java\jdk1.7.0\u 45\bin;D:\Jboss\Jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86\u 64
  • 我运行了x64 Dependency Walker,它告诉我找不到
    MSVCP100D.DLL
    MSVCR100D.DLL
    IESHIMS.DLL
    。我在
    c:\Windows\System32
    c:\Windows\SysWOW64
    文件夹中都找到了
    MSCV*.DLL
    文件,但每个文件夹中的文件大小不同。Dependency Walker已检测到驻留在
    system32
    中的其他文件的路径,因此我不理解它为什么找不到
    MSCV*.DLL
    文件。为了测试,我将它们放入与
    MyDriver.dll
    相同的文件夹
    ..\lib\win-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>
    
    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>
        <deployment>    
        <dependencies>
                <module name="com.mymodule" />
            </dependencies>
        </deployment>
    </jboss-deployment-structure>
    
    jboss部署结构

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

    {JBOSS_HOME}\modules\com\mymodule\main

    • MyModule.jar
      • module.xml
      • \lib\win-x86\u 64\
      • MyDriver.dll
      • ThirdPartyA.dll
      • ThirdPartyB.dll
      • ThirdPartyC.dll
      • ThirdPartyD.dll
      • \资源\数据\设置\
        • foo.optionfile
        • bar.optionfile

    我想出来了,下面是方法

  • 我首先从JBoss中取出DLL,并试图通过x64 dev/qa服务器上的JNI通过对本机方法的调用直接访问它。此操作失败,并出现相同的错误这意味着它不是JBoss。

  • 我从DLL中删除了对第三方库的引用,并尝试再次访问它。这也失败了,出现了相同的错误这意味着这不是第三方库或它们的路径问题。

  • 我创建了一个普通的DLL,它除了吐出一个字符串之外什么也不做,并尝试以与前两次相同的方式访问它。它也失败了这意味着它不是我的代码。

  • 我在VS2010中编译DLL作为调试。我将DLL重新编译为发行版这解决了问题。

  • 我找到了一个非常有用的答案,我再也找不到了,否则我会把它联系起来

    正如我现在所理解的,如果您在调试中编译DLL,它不应该是可再发行的。我在调试中编译并在x32开发服务器上使用的x32 DLL并非如此,但符合要求的x64 DLL确实如此。我编译为发行版,能够在整个应用程序中使用DLL


    我已经改变了构建未来开发可部署组件的常规。

    解决此类问题的最终工具是process monitor:。它将为您提供有关如何加载DLL的详细日志。