0

我有一个myproject.war部署到 JBoss 的 Java Web 应用程序。应用程序的一部分使用 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 最终版“Janus”
  • Java 运行时 1.7.0_45-b18。
  • 安装了 Visual Studio 2010 Redistributable 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)重新编译MyDriver.dll为 64 位
  • MyDriver.dll64 位版本的第三方 DLL 和资源文件夹放入模块文件夹中..\main\lib\win-x86_64\
  • modules将模块文件复制到文件夹下的路径
  • 创建module.xml
    • 与适当的资源MyModule.jar
      • 其中有MyDriverLoader加载的类MyDriver.dll
    • 参考sun.jdk我不是100%确定JNI需要的模块。

DLL是用

  • MFC 的使用:使用标准 Windows 库

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

java.lang.UnsatisfiedLinkError: D:\Jboss\jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86_64\MyDriver.dll: 找不到依赖库

这告诉我的是

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

我已经尝试了以下解决方案,但它们都不起作用并且错误仍然存​​在:

  1. 我已经安装了 Visual Studio 2010 Redistributable x64,它可能已经被打包了。
  2. 我已明确添加{JBOSS_HOME}\modules\com\mymodule\main\lib\win-x86_64到 Windows 环境变量PATH并确认了这一点,echo %PATH%其中包括:D:\Java\jdk1.7.0_45\bin;D:\Jboss\jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86_64;.
  3. 我运行了 x64 Dependency Walker,它告诉我MSVCP100D.DLLMSVCR100D.DLLIESHIMS.DLL没有找到。我MSCV*.DLLc:\Windows\System32C:\Windows\SysWOW64文件夹中都找到了这两个文件,但它们的文件大小不同。Dependency Walker 已检测到要驻留的其他文件的路径system32,所以我不明白为什么它没有找到这些MSCV*.DLL文件。为了测试,我将它们放入与 相同的文件夹...\lib\win-x86_64MyDriver.dll,但这没有改变。

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

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}\modules\com\mymodule\main

  • 我的模块.jar
    • 模块.xml
    • \lib\win-x86_64\
    • 我的驱动程序.dll
    • 第三方A.dll
    • 第三方B.dll
    • 第三方C.dll
    • 第三方D.dll
    • \资源\数据\设置\
      • foo.option 文件
      • bar.option文件
4

1 回答 1

1

我想通了,这就是方法。

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

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

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

  4. 我一直在将 VS 2010 中的 DLL 编译为 Debug。我将 DLL 重新编译为 Release。 这解决了这个问题。

我找到了一个帮助我无法再次找到的 SO 答案,否则我会链接它。

据我所知,如果您在 Debug 中编译 DLL,它不应该是可再分发的。我在 Debug 中编译并在我的 x32 开发服务器上使用的 x32 DLL 不是这种情况,但编译后的 x64 DLL 肯定是这种情况。我编译为 Release 并且能够在整个应用程序中使用 DLL。

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

于 2014-08-06T22:13:22.363 回答