JNI简介
JNI 全称为 Java Native Interface,Java 本地接口,是 Java 调用 Native 语言的一种特性。通过 JNI 可以使得 Java 与 C/C++ 机型交互,即可以在 Java 代码中调用 C/C++ 等语言的代码或者在 C/C++ 代码中调用 Java 代码。由于 JNI 是 JVM 规范的一部分,因此可以将我们写的 JNI 的程序在任何实现了 JNI 规范的 Java 虚拟机中运行。同时,这个特性使我们可以复用以前用 C/C++ 写的大量代码。JNI 是一种在 Java 虚拟机机制下的执行代码的标准机制。
JNI HelloWord
- 新建一个Java项目
- 编写代码
public class JNIDemo {
public native int add(int a,int b);
public native void sayHello();
}
public class JNIMain {
public static void main(String[] args) {
String strLibPath = "/home/HouXinLin/projects/c/jnidemo/hello.so";
System.load(strLibPath);
JNIDemo jniDemo = new JNIDemo();
System.out.println(jniDemo.add(1,2));
jniDemo.sayHello();
}
}
生成头文件
然后通过JDK工具javah生成JNIDemo类所需的头文件,javah 在JAVA_HOME\bin中。
进入项目src路径
执行以下命令,最后面的包名根据自己的来换。
javah -classpath . -jni -encoding UTF-8 com.company.JNIDemo
成功的话会在src目录下生成一个com_company_JNIDemo.h文件,内容如下。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_company_JNIDemo */
#ifndef _Included_com_company_JNIDemo
#define _Included_com_company_JNIDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_company_JNIDemo
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_company_JNIDemo_add
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_company_JNIDemo
* Method: sayHello
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_company_JNIDemo_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
- 编写C++新建一个cpp文件,将上面生成的头文件复制到同级目录下。
#include "com_company_JNIDemo.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_com_company_JNIDemo_sayHello(JNIEnv* env, jobject obj){
printf("Hello,JNI!\n");
};
JNIEXPORT jint JNICALL Java_com_company_JNIDemo_add(JNIEnv * env, jobject obj, jint a, jint b){
int rtn = (int)(a + b);
return (jint)rtn;
}
编译
下面命令中的JDK路径需要换成自己的,成功之后会在同级目录生成一个demo.so文件。这个文件就是我们通过System.loadLibrary()要加载的,System.loadLibrary() 可以加载 dll(Windows)或 so(Linux)库。
gcc demo.cpp -std=c++11 -fPIC -shared -I /home/HouXinLin/apps/java/jdk/jdk1.8.0_241/include -I /home/HouXinLin/apps/java/jdk/jdk1.8.0_241/include/linux -lm -o ./demo.so
运行
Java 数据类型与 JNI 类型映射
Java 中的基本类型通过 javah 工具生成 .h 文件的时候,这些基本类型分别对应的类型是 jboolean,jbyte,jchar,jshort,jint,jlong,jfloat,jdouble。下面是详细的 Java 数据类型与 JNI 类型映射表:
boolean | jboolean | C/C++8 位整型 |
byte | jbyte | C/C++ 带符号的 8 位整型 |
char | jchar | C/C++ 无符号的 16 位整型 |
short | jshort | C/C++带符号的 16 位整型 |
int | jint | C/C++带符号的 32 位整型 |
long | jlong | C/C++带符号的 64 位整型 |
float | jfloat | C/C++32 位浮点型 |
double | jdouble | C/C++64 位浮点型 |
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 | 双浮点型数组 |