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

开发 后端
Java以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。

Java通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使Java可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、Java中所需要做的工作

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

Java代码

static {        
System.loadLibrary(“goodluck”);        
}    
static {   
System.loadLibrary(“goodluck”);   

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

在这里,库的扩展名字可以不用写出来,究竟是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();  
  • 1.
  • 2.
  • 3.
  • 4.

然后编译该Java程序文件,生成CLASS,再用JavaH命令,JNI就会生成C/C++的头文件。

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

Java代码

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());   
}   

  • 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.

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

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

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

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

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

Java代码

/* 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 
  • 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.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.

在具体实现的时候,我们只关心两个函数原型 :

Java代码

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);  

JNIEXPORT jint JNICALL Java_testdll_get (JNIEnv *, jclass);

和Java代码

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代码

#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;   

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

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

把goodluck.dll拷贝到testdll.class的目录下,Java testdll运行它,就可以观察到结果了。

【编辑推荐】

  1. Java连接MySQL中文乱码处理
  2. 在Java应用程序中使用Jfreechart配置
  3. Java虚拟机内部构成浅析
  4. 浅谈Java线程的生命周期
  5. 关于Java继承的一些复习
责任编辑:彭凡 来源: javaeye
相关推荐

2012-04-28 15:28:21

JNI混合编程Java

2010-06-17 11:51:20

java.net DLLC#

2009-12-08 17:15:43

PHP调用Java语言

2012-03-20 11:37:24

JavaJNI

2009-08-03 12:57:27

C#调用DLL

2014-05-15 16:33:05

C++CLI调用C#

2009-08-31 18:05:14

C#调用WalkTre

2009-08-31 16:33:28

C#调用Dispose

2009-08-11 11:07:49

Java调用C# we

2010-06-23 13:11:36

JavaJNI

2009-07-31 17:28:35

C#语言调用DLL

2011-04-08 09:52:44

C++C#DLL

2014-09-02 10:43:45

RedisRPC

2010-02-05 15:59:26

C++函数重载

2011-06-08 09:19:26

Android JNI

2009-09-01 11:04:59

C#调用扩展方法

2024-05-16 12:33:37

C#编程指针

2011-12-28 10:08:24

Javajni

2010-01-22 14:46:25

C++语言

2011-07-20 10:30:29

C语言
点赞
收藏

51CTO技术栈公众号