Java native interface(JNI)技术简单应用


手上一个项目需要通过usb口去读取usbkey的信息,厂家提供的只有C/C++的接口,而主应用是java的,所以需要使用java去调用动态链接库,所以花了点时间研究了下JNI技术,jdk对JNI技术封装得很到位,使用起来非常简单,JNI技术最关键还是在于jni数据类型和本地数据类型的转换。先简单罗列下JNI的创建过程:

首先需要写一个java类,然后定义需要使用C/C++去实现的方法(虽然说jni是java native interface,但是目前只支持c/c++实现),使用native关键字声明。这里写一个简单的例子:

TestJNI.java

[java:nogutter]

  1. package test.jni;  
  2.   
  3. public class TestJNI  
  4. {  
  5.       
  6.     static  
  7.     {  
  8.          System.loadLibrary("TestJNI");  
  9.          //这个是之后产生的库的名字,不需要加后缀,   
  10.              //自动根据系统找.dll或者.so;   
  11.     }  
  12.   
  13.     public native String helloWorld();  
  14.       
  15.     public static void main(String[] args)  
  16.     {  
  17.         TestJNI t = new TestJNI();  
  18.         System.out.println(t.helloWorld());  
  19.     }  
  20. }  

然后将以上文件使用javac编译,然后使用javah命令,如下:

javac test/jni/TestJNI.java

javah test.jni.TestJNI

之后会得到一个test_jni_TestJNI.h的头文件,内容如下:

test_jni_TestJNI.h

[cpp]

  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>   
  3. /* Header for class test_jni_TestJNI */  
  4.   
  5. #ifndef _Included_test_jni_TestJNI   
  6. #define _Included_test_jni_TestJNI   
  7. #ifdef __cplusplus   
  8. extern "C" {  
  9. #endif   
  10. /* 
  11.  * Class:     test_jni_TestJNI 
  12.  * Method:    helloWorld 
  13.  * Signature: ()Ljava/lang/String; 
  14.  */  
  15. JNIEXPORT jstring JNICALL Java_test_jni_TestJNI_helloWorld  
  16.   (JNIEnv *, jobject);  
  17.   
  18. #ifdef __cplusplus   
  19. }  
  20. #endif   
  21. #endif  

然后编写c/c++实现,如下:

TestJNI.c

[cpp]

  1. #include <stdio.h>   
  2. #include <jni.h>   
  3. #include <windows.h>   
  4.   
  5. #include "test_jni_TestJNI.h"   
  6.   
  7. JNIEXPORT jstring JNICALL Java_test_jni_TestJNI_helloWorld  
  8.   (JNIEnv * env, jobject object){  
  9.     //在c中必须给形式参数声明变量名,C++中可以不用,头文件中不需要修改;   
  10.     const char* str = "helloWorld";  
  11.     return (*env)->NewStringUTF(env,str);  
  12.     //C++中可以直接env->NewStringUTF(str),这个函数编码中文会乱码;   
  13.       
  14. }  

使用VC编译成TestJNI.dll,编译是需要引入jre/include文件夹和jre/include/win32文件夹。

将TestJNI.dll拷贝至刚才test.jni.TestJNI的classpath下面,然后运行java test.jni.TestJNI就能得到输出了,一些在编写C程序时遇到的问题都在c代码中注释了,希望能给遇到同样问题的朋友一个借鉴。

相关内容