Java通过JNI调用C语言的方法

来源:互联网 发布:java程序员发展规划 编辑:程序博客网 时间:2024/04/24 12:55

Java以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。
Java通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使Java可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、Java中所需要做的工作

在Java程序中,首先需要在类中声明所调用的库名称,如下:

Java代码

static {        System.loadLibrary(“goodluck”);        }    static {   System.loadLibrary(“goodluck”);   } 在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:

Java代码

public native static void set(int i);      public native static int get();     public native static void set(int i);   public native static int get();  然后编译该Java程序文件,生成CLASS,再用JavaH命令,JNI就会生成C/C++的头文件。

例如程序testdll.Java,内容为:

Java代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class testdll     
 {     
 static   
   {      
System.loadLibrary("goodluck");      
}      
public native static int get();     
public native static void set(int i);  
public static void main(String[] args)      
{     
 testdll test = new testdll();       
 test.set(10);      
 System.out.println(test.get());    
  }       
 }   
 public class testdll  
 {   static 
{   
System.loadLibrary("goodluck"); 
 }   
public native static int get();   
public native static void set(int i);  
 public static void main(String[] args)   
{   
testdll test = new testdll();  
 test.set(10);   
System.out.println(test.get());   
}   
}



用Javac testdll.Java编译它,会生成testdll.class。

再用Javah testdll,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

二、C/C++中所需要做的工作

对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到Java程序的路径下面,就可以用Java调用C/C++所实现的功能了。

接上例子。我们先看一下testdll.h文件的内容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/* DO NOT EDIT THIS FILE - it is machine generated */      
#include          
/* Header for class testdll */          
#ifndef _Included_testdll          
#define _Included_testdll          
#ifdef __cplusplus         
 extern "C"
 {          
#endif          
/*       
 * Class: testdll        
* Method: get        
* Signature: ()I       
 */          
JNIEXPORT jint JNICALL Java_testdll_get          (JNIEnv *, jclass);         
 /*       
 * Class: testdll        
* Method: set        
* Signature: (I)V      
  */          
JNIEXPORT void JNICALL Java_testdll_set          (JNIEnv *, jclass, jint);         
 #ifdef __cplusplus          
}          
#endif         
 #endif     
/* DO NOT EDIT THIS FILE - it is machine generated */  
 #include   
 /* Header for class testdll */    
#ifndef _Included_testdll    
#define _Included_testdll    
#ifdef __cplusplus    extern "C" 
{    
#endif   
 /*    
* Class: testdll    
* Method: get    
* Signature: ()I    
*/    
JNIEXPORT jint JNICALL Java_testdll_get    (JNIEnv *, jclass);   
 /*    
* Class: testdll    
* Method: set    
* Signature: (I)V   
 */    
JNIEXPORT void JNICALL Java_testdll_set    (JNIEnv *, jclass, jint);   
 #ifdef __cplusplus    
}    
#endif    
#endif


Java代码

?
1
2
3
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);   
  
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);



和Java代码

?
1
2
3
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);   
  
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint);



这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使Java的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是Java_再加上Java程序的package路径再加函数名组成的。参数中,我们也只需要关心在Java程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用testdll.cpp文件具体实现这两个函数:

Java代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "testdll.h"       int i = 0;       
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)      
 {       
return i;       
}       
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j)       
 {       
 i = j;       
 }   
 #include "testdll.h"   
int i = 0;   
JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass)  
 {  
 return i;  
 }   
JNIEXPORT void JNICALL Java_testdll_set (JNIEnv *, jclass, jint j) 
  {  
 i = j; 
  }

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与Java中需要调用的一致,这里就是goodluck.dll

把goodluck.dll拷贝到testdll.class的目录下,Java testdll运行它,就可以观察到结果了。
http://developer.51cto.com  

原创粉丝点击