由于最近项目中需要读取读卡器上的信息,从来没有接触过使用java调用底层动态链接库Dll的这些东西,就到网上搜了一大堆的资料,然后慢慢摸索,学习了JNI和Jnative两种通过Java方式调用Dll文件的方法。
JNI的步骤如下:
1.在java类中先定义了一个方法,不用实现。
public native static int add(int a,int b);//函数声明如果对native用法不清楚的,可以去google看看,相信就很清楚了。 2.在java类中载入dll文件,dll文件不用扩展名,会自动识别。还有一种方法是用System.load(xxx);里面是需要绝对路径的,扩展名也不能省。
static { System.loadLibrary("TestDll");//载入dll }3. java类写好后用javac xxx.java进行编译 4. 使用javah -jni xxx.生成头文件。 第3.4点需要注意的是:一般我们都是在做项目,java类前面的包名肯定少不了,所以我们在命令行中编译时需要cd 到指定的java类路径下,例如我在Myeclipse中建立的一个工程,路径如下:D:\workspace\DiskNumber\src\com\tjn\test 先要cd
D:\workspace\DiskNumber\src\com\tjn\test 然后运行javac TestDll.java 生成class文件后,需要生成头文件,输入set classpath=D:\workspace\DiskNumber\src ,到项目的src根目录下,然后运行javah -jni com.tjn.test.TestDll,会生成一个
com_tjn_test_TestDll.h的文件,然后改头文件的名,我这里改为TestDll.h,需要和System.loadLibrary()中的名称相对应。如果不在项目里,单个文件运行当然没问题。但是在项目中生成头文件,需要如上进行操作,否则会报找不到类的错误。
5.可以看到生成的头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_tjn_test_TestDll */ #ifndef _Included_com_tjn_test_TestDll #define _Included_com_tjn_test_TestDll #ifdef __cplusplus extern "C" { #endif /* * Class: com_tjn_test_TestDll * Method: add * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_tjn_test_TestDll_add (JNIEnv *, jclass, jint, jint); #ifdef __cplusplus } #endif #endif这是javah根据java类自动生成的头文件,注释我们不管,可以看到里面的方法命名是Java_包名_类名_方法名,需要传递两个int类型的参数,在这个头文件中已经自动转换成jint类型。这个方法也没有任何的实现,相当于java中的接口,我们现在创建一个xx.c的文件来实现这里定义的方法。
JNIEXPORT jint JNICALL Java_com_tjn_test_TestDll_add (JNIEnv *, jclass, jint x, jint y) { return x+y; }如何编译生成dll,这里就不加详述了。我这个例子是用vc++6.0做的.将生成的TestDll.dll文件放置到windows/system32中,然后在java类中调用就可以啦。 6.在java类的main函数中打印输出dll计算显示的返回结果
public static void main(String[] args) { int r = TestDll.add(30,20); System.out.println("result = "+r); }这里需要注意的是由于是用javah -jni 生成的头文件包含了包名,(从头文件生成的方法名就可以看出来),将这个Java类放置到其他路径下并能调用相应的dll文件,因为该dll文件只认定那个src路径下的com.tjn.test.TestDll类。所以在其他地方或者其他工程引用的话,需要将TestDll类打成jar包,在别的工程导入这个jar包,并做如下调用: 比如我在另外一个工程中的类main函数中调用
public static void main(String[] args) { int a=com.tjn.test.TestDll.add(20, 50); System.out.println(a); }调用jar包里面的方法,这是这个类就还在这个com.tjn.test的路径下,所以就不会报说找不到dll的异常啦!
JNative调用dll文件比JNI简单的多,改天整理后再说吧!也可以自己网上搜索,资料都差不多。
给个参考资料http://blog.csdn.net/pengchua/archive/2008/06/11/2534842.aspx
学习过程中的一些参考的相关资料:
1. http://www.blogjava.net/orangewhy/archive/2007/05/
2.http://www.iteye.com/topic/304594
3.http://yinxu.iteye.com/blog/206163
4.http://read.newbooks.com.cn/info/143806.html
以上这些是我在学习JNI过程中有碰到过的问题,记录一下,做个笔记,同时如果有碰到类似问题的朋友可以和我互相交流,一起学习,进步。
相关资源:JAVA JNI调用DLL完整步骤