为什么这个基于JNI的JBoss模块抛出错误“无法找到依赖库”? [英] Why is this JNI-based JBoss module throwing Error "Can't find dependent libraries"?

查看:208
本文介绍了为什么这个基于JNI的JBoss模块抛出错误“无法找到依赖库”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



以前的环境构建




  • 32位Windows Server 2003

  • JBoss 6.X

  • Java 1.6.X



    • 新建环境构建




      • 64位Windows Server 2008 R2,SP1 7601)

      • JBoss AS 7.2.0 FinalJanus

      • Java Runtime 1.7.0_45-b18。

      • 安装Visual Studio 2010 Redistributable x64



      在旧系统上,自定义DLL和第三方库毫无意义地转储到 C:\Windows \System32\ ,应用程序能够通过JNI成功连接到它们。第三方库包括几个DLL,一些ICC配置文件和一个资源文件夹,其中包含True类型字体,配置和其他文件的子文件夹。



      迁移,一个JBoss模块被创建为包含JNI代码。将Java / JNI代码移动到 MyModule.jar ,并将 MyDriver.dll 重新编译为x64。



      我有




      • 使用Visual Studio 2010(10.0.40219.1 SP1Rel)重新编译 MyDriver.dll 以用于64位

      • 放置 MyDriver .dll 和64位版本的第三方DLL和资源文件夹复制到模块文件夹 .. \main\lib\win-x86_64\

      • 将模块文件复制到 modules 文件夹下的路径

      • 使用适当的资源创建 module.xml

        • MyModule.jar

          • 其中有 MyDriverLoader 类,它加载 MyDriver.dll sun.jdk 的引用





        这个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. $ b

          我试过下面的解决方案,但没有一个工作,并且错误仍然存​​在:


          1. 我安装了Visual Studio 2010

          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\我已经运行了x64 Dependency Walker,它告诉我 MSVCP100D.DLL
          3. / code>,未找到MSVCR100D.DLL IESHIMS.DLL 。我在 c:\Windows \System32 和<$ c $中都找到了 MSCV * .DLL c> C:\Windows \SysWOW64 文件夹,但它们在每个文件大小不同。依赖Walker已经检测到其他文件驻留在 system32 的路径,所以我不明白为什么它找不到 MSCV * .DLL 文件。要测试,我把他们放到同一个文件夹 ... \lib \win-x86_64 作为 MyDriver.dll




            $ b

            module.xml

              < module xmlns =urn:jboss:module:1.1name =com.mymodule> 

            < main-class name =com.mymodule.DriverClassName/>

            < resources>
            < resource-root path =MyModule.jar/>
            < / resources>

            < dependencies>
            < module name =sun.jdk/>
            < / dependencies>
            < / module>

            MyDriverLoader.java strong>

              public class MyDriverLoader {

            / **
            * Load C ++ Library
            * /
            static {

            System.loadLibrary(MyDriver);
            }

            / **
            *返回C ++ DLL版本的Native方法。
            * /
            public native static String getVersion();

            / **
            *主方法调用getVersion。
            *
            * @param args
            * /
            public static void main(String args []){

            System.out.println(MyDriverLoader调用MyDriver.dll版本+ getVersion());
            }
            }

            jboss-部署结构

             < 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_64\

              • MyDriver.dll

              • ThirdPartyA.dll

              • ThirdPartyB.dll

              • ThirdPartyC.dll

              • ThirdPartyD.dll

              • \Resource\Data\Settings\

                • foo.optionfile

                • bar.optionfile





            解决方案

            是如何。


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


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


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


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


            我发现一个SO答案,



            我现在明白了,如果你在Debug中编译一个DLL,它不应该是可重新分发的。在我在Debug中编译并在我的x32开发服务器上使用的x32 DLL中并不是这样,但是对于编译的x64 DLL肯定是这样。我编译为Release,并且能够在我的应用程序中使用DLL。我改变了构建开发可部署的例程。


            I have a Java web application myproject.war deployed to JBoss. A portion of the application uses JNI to connect to a C++ DLL, which calls functions from a set of third-party libraries. We are migrating this application from a x32 server to a x64 server.

            Prior Environment Build

            • 32-bit Windows Server 2003
            • JBoss 6.X
            • Java 1.6.X

            New Environment Build

            • 64-bit 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 installed

            On the old system, the custom DLL and third-party libraries were unceremoniously dumped into C:\Windows\System32\ and the application was able to successfully connect to them via JNI. The third-party libraries include several DLLs, some ICC Profiles, and a Resource folder with sub-folders of files including True-type fonts, configurations and other files.

            For the migration, a JBoss module was created to contain the JNI code. The Java / JNI code was moved to MyModule.jar, and MyDriver.dll was recompiled to x64. x64 versions of the third-party libraries were obtained.

            I have

            • recompiled MyDriver.dll for 64-bit using Visual Studio 2010 (10.0.40219.1 SP1Rel)
            • placed MyDriver.dll and 64-bit versions of the third-party DLLs and resource folder into the module folder ..\main\lib\win-x86_64\
            • copied the module files to a path under the modules folder
            • created module.xml
              • with the appropriate resource MyModule.jar.
                • which has class MyDriverLoader which loads MyDriver.dll.
              • with a reference to module sun.jdk which I am not 100% certain is needed for JNI.

            The DLL is compiled with

            • Use of MFC: Use Standard Windows Libraries

            No matter what I do, when starting the application, JBoss throws the following Java Error:

            java.lang.UnsatisfiedLinkError: D:\Jboss\jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86_64\MyDriver.dll: Can't find dependent libraries

            What this tells me is

            1. JBoss can detect the correct DLL from the module and therefore I've configured the module correctly.
            2. Some dependent library is not in the path of JBoss.

            I have tried the following solutions, but none of them worked and the Error persists:

            1. I have installed Visual Studio 2010 Redistributable x64, which was probably already packaged in anyway.
            2. I have explicitly added {JBOSS_HOME}\modules\com\mymodule\main\lib\win-x86_64 to Windows environment variable PATH and confirmed this with echo %PATH% which includes: D:\Java\jdk1.7.0_45\bin;D:\Jboss\jboss-7.2.0.Final\modules\com\mymodule\main\lib\win-x86_64;.
            3. I've run x64 Dependency Walker, which tells me MSVCP100D.DLL, MSVCR100D.DLL and IESHIMS.DLL are not found. I have found both MSCV*.DLL files in both c:\Windows\System32 and C:\Windows\SysWOW64 folders, but they are different file sizes in each. Dependency Walker has detected the paths of other files to reside in system32, so I do not understand why it isn't finding the MSCV*.DLL files. To test, I threw them into the same folder ...\lib\win-x86_64 as MyDriver.dll, but this changed nothing.

            What can I do to resolve this?

            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>
            

            folder structure of module mymodule:

            {JBOSS_HOME}\modules\com\mymodule\main

            • MyModule.jar
              • module.xml
              • \lib\win-x86_64\
              • MyDriver.dll
              • ThirdPartyA.dll
              • ThirdPartyB.dll
              • ThirdPartyC.dll
              • ThirdPartyD.dll
              • \Resource\Data\Settings\
                • foo.optionfile
                • bar.optionfile

            解决方案

            I figured it out, and here is how.

            1. I first took the DLL out of JBoss and tried to access it directly from a call to a native method via JNI on the x64 dev/qa server. This failed with the same error. This meant it was not JBoss.

            2. I stripped references to the third-party libraries from the DLL and tried to access it again. This also failed with the same error. This meant it was not the third-party libraries or a path issue with them.

            3. I created a plain DLL which did nothing but spit out a string and tried to access it in the same way as the prior two times. It also failed. This meant it was not my code.

            4. I had been compiling the DLL in VS 2010 as Debug. I recompiled the DLL as Release. This solved the issue.

            I found a SO answer that helped that I cannot find again, otherwise I would link it.

            As I now understand it, if you compile a DLL in Debug, it should not be redistributable. This was not the case with the x32 DLLs that I compiled in Debug and used on my x32 development servers, but was certainly the case with the complied x64 DLL. I compiled as Release and was able to use the DLL throughout my application. I have changed the routine for building a development deployable.

            这篇关于为什么这个基于JNI的JBoss模块抛出错误“无法找到依赖库”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆