我有一个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,因此我已经正确配置了模块。
- 某个依赖库不在JBoss的路径中。
我尝试了以下解决方案,但都不起作用,错误仍然存在:
- 我已经安装了Visual Studio 2010 Redistributable x64,它可能已经打包在里面了。
- 我已经明确地将
{JBOSS_HOME}modulescommymodulemainlibwin-x86_64
添加到Windows环境变量PATH
中,并与echo %PATH%
确认这一点,其中包括:D:Javajdk1.7.0_45bin;D:Jbossjboss-7.2.0.Finalmodulescommymodulemainlibwin-x86_64;
。 - 我已经运行了x64 Dependency Walker,它告诉我没有找到
MSVCP100D.DLL
,MSVCR100D.DLL
和IESHIMS.DLL
。我在c:WindowsSystem32
和C: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
我想出来了,方法如下。
-
我首先将DLL从JBoss中取出,并尝试通过x64 dev/qa服务器上的JNI调用本机方法直接访问它。这失败了,出现了同样的错误。
-
我从DLL中剥离了对第三方库的引用,并试图再次访问它。这也以同样的错误失败了。这意味着不是第三方库或它们的路径问题。
-
我创建了一个普通的DLL,它什么也不做,只是吐出一个字符串,并试图以与前两次相同的方式访问它。它也失败了。
-
我一直在编译vs2010中的DLL作为调试。我将DLL重新编译为Release。
我找到了一个很有帮助的答案,我再也找不到了,否则我会把它链接起来。
正如我现在所理解的,如果你在调试中编译一个DLL,它不应该是可重新分发的。我在Debug中编译并在x32开发服务器上使用的x32 DLL不是这种情况,但编译后的x64 DLL肯定是这种情况。我将其编译为Release,并能够在整个应用程序中使用DLL。
我已经更改了构建未来开发可部署的例程。