JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。JNI标准至少要保证本地代码能工作在任何Java 虚拟机环境下。
JNI编写步骤:
- 编写带有native声明的方法的java类
- 使用javac命令编译所编写的java类
- 使用javah + java类名生成扩展名为h的头文件
- 使用C/C++实现本地方法
- 将C/C++编写的文件生成动态连接库
首先,我们来编写JAVA类
public class HelloJNI
{
// 所有native关键词修饰的都是对本地的声明
public native void displayHelloJNI();
static
{
// 载入本地动态链接库库
System.loadLibrary("HelloJNI");
}
public static void main(String[] args)
{
new HelloJNI().displayHelloJNI();
}
}
编写完JAVA类后,我们需要对其进行编译获得字节码文件:javac HelloJNI.java
然后我们要生成扩展名为h的头文件:javah HelloJNI
生成的头文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: displayHelloJNI
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloJNI_displayHelloJNI
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
下面我们需要引入刚才生成的头文件并实现其方法,最终生成动态链接库。
c源文件代码如下:
#include <stdio.h>
#include "HelloJNI.h"
JNIEXPORT void JNICALL Java_HelloJNI_displayHelloJNI(JNIEnv *env, jobject obj)
{
printf("HelloJNI\n");
}
这里使用VC的编译器:cl -I%java_home%\include -I%java_home%\include\win32 -LD HelloJNIImpl.c -FeHelloJNI.dll
我们需要将生成的HelloJNI.dll放到JAVA的类路径下,最后运行JAVA程序。
控制台会输出:HelloJNI
到此,最简单的JNI编写过程已经完了。下面我们来总结一下。
JNI数据类型对应关系
基本类型
Java类型 | 本地C类型 | 说明 |
---|---|---|
boolean | jboolean | 无符号8位整型(unsigned char) |
byte | jbyte | 有符号8位整型(char) |
char | jchar | 无符号16位整型(unsigned short) |
short | jshort | 有符号16位整型(short) |
int | jint | 有符号32位整型(int) |
long | jlong | 有符号64位整型(long) |
float | jfloat | 32位浮点型(float) |
double | jdouble | 64位浮点型(double) |
引用数据类型
Java类型 | 本地C类型 | 说明 |
---|---|---|
Object | jobject | 任何JAVA对象,或者没有对应JAVA类型的对象 |
Class | jclass | Class类对象 |
String | jstring | 字符串对象 |
Object[] | jobjectArray | 任何对象的数组 |
boolean[] | jbooleanArray | 布尔型数组 |
byte[] | jbyteArray | 比特型数组 |
char[] | jcharArray | 字符型数组 |
short[] | jshortArray | 短整型数组 |
int[] | jintArray | 整型数组 |
long[] | jlongArray | 长整型数组 |
float[] | jfloatArray | 浮点型数组 |
double[] | jdoubleArray | 双浮点型数组 |
特殊类型
Java类型 | 本地C类型 | 说明 |
---|---|---|
void | void | N/A |
注意:
1. 引用数据类型则不能直接使用,需要根据JNI函数进行相应的转换后,才能使用。
2. 多维数组(包括二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值 。
例如:二维整型数组就是指向一维数组的数组,其声明使用方式如下:
//获得一维数组 的类引用,即jintArray类型
jclass intArrayClass = env->FindClass("[I");
//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为dimion
jobjectArray obejctIntArray = env->NewObjectArray(dimion ,intArrayClass , NULL);