最近在做的工作要用到本地方法,需要在Java中加载不少动态链接库(以下为方便延用Windows平台下的简写dll,但并不局限于Windows)。刚刚把程序跑通,赶紧把一些心得写出来,mark。也希望对大家的类似工作有所帮助
首先,应当明确,dll有两类:(1)Java所依赖的dll和,(2)dll所依赖的dll。正是由于第(2)种dll的存在,才导致了java中加载dll的复杂性大大增加,许多说法都是这样的,但我实验的结果却表明似乎没有那么复杂,后面会予以详细阐述。
其次,Java中加载dll的方式也有两种:(1)通过调用System.loadLibrary(String filename)和,(2)通过调用System.load(String filename)方法。其底层都是通过使用ClassLoader中的loadLibrary(Class fromClass, String name, boolean isAbsolute)方法来实现的,区别仅在于(1)中的filename必须是绝对路径,(2)中的filename只能是dll名,不允许包含文件夹。
再者,Eclipse是一个相当强大的平台,其提供的BundleClassLoader的强大是一个很重要的原因,对于dll的加载也有自己一套很别致的做法,值得我们采纳。
根据上面的介绍,分两部分阐述Java中加载dll面临的主要问题和解决途径。
1. 在一般Java程序中加载dll
我所做的工作,需要加载的dll如下:
DigitDll.dll
DsivsAcct.dll
DsivsComm.dll
DsivsTrans.dll
JBPack.dll
XCodeDll.dll
ImageDllCtrl.dll
yhfiche.dll
yhocr.dll
yhbill.dll
TSealSvrDll.dll
TImg.dll
TImage.dll
直接调用的是TImage中的若干方法,列表中TImage之前的所有其直接或间接依赖的,不仅要把所有的dll load全,更要注意他们之间的依赖关系,被依赖dll一定要先加载,否则就会报错:UnsatisfiedLinkError。故而,首先应理清dll 之间的依赖关系,上面的列表已经是处理过的了。
接下来是设置JVM的搜索路径,使其能够找到你的dll。JVM的搜索路径由java.library.path系统属性决定,其默认值为系统环境变量中的PATH 内容。因此,可以通过修改PATH变量来达到设置java.library.path属性的目的(改变之后Eclipse需要重新启动),一般的方法是在 PATH中加入dll所在文件夹的绝对路径。另一种方法是在Java命令的参数中加入“-Djava.library.path=dll所在文件夹的绝对路径”来设置(可以用;分开多个路径)。对于Eclipse开发环境上的应用程序,可以通过修改其启动参数,在VM arguments编辑框中加入前述参数。对于打包出来的Eclipse安装包,可编辑其启动目录下的application.ini(假设其启动文件为 application.exe),在-vmargs后加入前述参数来设置java.library.path的值。需要注意的是,一旦JVM已经启动,则无法再修改java.library.path的内容了,也就是说,通过:
System.setProperty("java.library.path", "c:\mylib");
这样的方式是无法达到目的的,因为该属性是只读的。Sun公司的论坛上曾经讨论过如何在代码中修改java.library.path的问题,结论是:不能通过代码修改!如果嫌"java -Djava.library.path=c:\mylib"这样的方式写得太死,也只能是通过shell编程之类的方法对路径进行预处理,以改善其灵活性了。
如果你的dll是封装在jar包中的,则需要首先将之解压缩到一个临时路径上,然后再将该路径加入到Djava.library.path中,或者干脆将其解压缩到系统路径上。
2. 在Eclipse平台上加载dll
上面提到,Java中对本地库路径的设置方式做得太死,这也是我自己的切身体会,但令人感到欣慰的是我们的Eclipse平台的提供了一套比较灵活的做法,通过eclipse提供的BundleClassLoader,你可以将dll封在plugin中,既不需要在使用时解压缩,也不需要额外设置 java.library.path属性,BundleClassLoader会自行到以相对plugin根目录的指定目录下去查找你的dll,这些目录是:ws/win32/, os/win32/x86/, os/win32/, nl/zh/CN/, nl/zh/,见org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader和 org.eclipse.core.runtime.internal.adaptor.EclipseClassLoadingHook。
我的目录设置是:
.classpath
.cvsignore
.project
build.properties
classes
CVS
lib
META-INF
os
plugin.xml
src
我把所有的dll都放到了os下面的win32目录内,同样可以建立ws/win32等目录用于放置本地库。如此处理之后,不用再修改任何系统变量就可以顺利加载本地库了。
另外,Eclipse还在MANIFEST文件中提供了Bundle-NativeCode的设置项,也是用于加载本地库的,有待进一步研究
本文匆匆而就,希望对自己对大家都能有所帮助
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xiaolang85/archive/2008/12/25/3604971.aspx
分享到:
相关推荐
标题“Java加载dll,导致Java进程内存泄露”涉及到的是Java平台与本地库(DLL)交互时可能出现的问题。在Java中,通过Java Native Interface (JNI) 可以调用C/C++编写的动态链接库(DLL),实现Java代码与本地代码的...
java 加载dll 异常,包含调试运行和打jar 可以参考https://blog.csdn.net/ADdhtfdhdg/article/details/108754087
4. **加载DLL和调用方法**: 在Java代码中,使用`System.loadLibrary`加载本地库,然后可以调用`DesUtil.encrypt`和`DesUtil.decrypt`进行DES加密解密。 ```java public class Main { public static void main...
### Windows环境下Java加载DLL...以上介绍了几种在Windows环境下通过Java加载DLL的方法,每种方法都有其适用场景和局限性。开发者可以根据实际需求选择最适合的方式。在处理本地库时,还需要注意兼容性和安全性等问题。
3. **加载DLL**:使用`LibraryLoader`或自定义`NativeLibrary`实例加载DLL文件。 4. **调用DLL函数**:通过接口实例调用DLL中的函数,传递必要的参数,包括回调函数接口实例。 5. **处理回调**:在定义的回调函数...
- **加载DLL**:使用JNative库提供的API,如`JLibrary.loadLibrary()`,加载DLL文件。确保DLL文件与Java应用程序在同一目录下,或者指定正确的路径。 - **定义本地方法**:在DLL的C/C++代码中,实现与Java中声明的...
总结来说,Java调用DLL文件主要依赖于JNative库,通过定义Java接口、加载DLL、获取函数句柄、创建代理对象以及调用函数等步骤实现。这种方法使得Java开发者能够充分利用C/C++库的功能,同时也保持了Java的跨平台特性...
3. **加载DLL**:使用`Native.loadLibrary`方法加载DLL库,传入DLL的名称和定义接口的类。 4. **调用函数**:现在你可以像调用Java方法一样调用DLL中的函数了。 示例代码: ```java public interface MyDLL ...
5. 在Java程序中编译并运行,Java会自动加载DLL并调用native方法。 除了JNI,还可以使用JNA库来调用DLL。JNA是一种更高级、更易用的接口,它允许Java直接映射到DLL中的函数,而无需编写本地代码。使用JNA时,你只...
本文将详细介绍如何在Java中调用DLL文件,并探讨几种常见的调用方法。 ### Java调用DLL的基本概念 在Java中调用DLL文件主要通过Java Native Interface (JNI)、JAWINJNative和JNA等技术来实现。这些技术允许Java...
创建一个Java类,声明native方法,并使用`System.loadLibrary`加载DLL。 ```java public class DllCall { static { System.loadLibrary("myDll"); } public native int add(int a, int b); public ...
本文将详细介绍如何在Java中调用C++实现的DLL,并通过一个具体的示例来阐述这一过程。 首先,我们要了解Java Native Interface (JNI),它是Java平台标准的一部分,允许Java代码和其他语言写的代码进行交互。JNI在...
- `System.loadLibrary()`:这是Java中加载DLL的主要方法,它会查找系统路径下的相应DLL文件。如果DLL不在系统路径中,需要手动指定完整路径。 2. **创建DLL** - 使用C++ IDE(如Visual Studio)或命令行工具(如...
2. **Web浏览器兼容**: 当用户访问包含Java applet的网页时,这个DLL文件帮助浏览器加载并运行这些小应用程序,实现交互式内容。 3. **应用程序组件**: 许多第三方软件依赖于msjava.dll来运行其Java相关的组件或...
3. **加载DLL**:使用`Library`接口的`Util.loadLibrary`方法加载DLL。例如,对于名为`myDll`的DLL,可以写成`LibraryLoader.loadLibrary("myDll")`。 4. **实现DLL接口**:JNA会自动将Java接口映射到DLL中的相应...
3. **加载Library**:使用`LibraryLoader`加载DLL。通常,我们使用`Native.loadLibrary`方法指定DLL的名称: ```java MyDll dll = (MyDll) Native.loadLibrary("mydll", MyDll.class); ``` 其中,"mydll"是DLL的...