JNI 的全称是 Java Native Interface,是一种 Java 的 Native 编程接口,支持 Java 与 C/C++ 直接相互调用,从 JDK 1.0 开始提供。
基本使用流程
通过一个简单的例子来介绍下 JNI 的使用方法,对整体 JNI 有个初步的整体概念。
1. native method
定义一个 Java 类,其中包含 native 方法,另外通过 loadLibrary 来加载动态库。
package jni; class JniDemo { static { // 这里是加载一个名叫 libjnidemo 的动态库,后缀会根据OS不同而不同 System.loadLibrary("jnidemo"); } public native void nativeMethod(); }
额外说明:
- 动态库需要在 java 启动参数的 -Djava.library.path= 中定义,否则会报动态库找不到的错误
- 对于苹果的 M1 电脑,需要额外注意动态库是属于那种架构(aarch64 和 x86_64),需要与使用的 jdk 保持一致
2. generate header
JDK 默认自动的工具可以生成头文件
# 1. javac -h:java 编译为 class,并且生成头文件 ${JAVA_HOME}/bin/javac -h . jni/JniDemo.java # 2. javah:需要在 classpath 下找到已经编译好的 class ${JAVA_HOME}/javah jni.JniDemo
生成的头文件示例如下:
// filename: jni_JniDemo.h /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class jni_JniDemo */ #ifndef _Included_jni_JniDemo #define _Included_jni_JniDemo #ifdef __cplusplus extern "C" { #endif /* * Class: jni_JniDemo * Method: nativeMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_jni_JniDemo_nativeMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
3. implementation
引入头文件,实现其对应的函数
// filename: JniDemo.cc #include "jni_JniDemo.h" JNIEXPORT void JNICALL Java_jni_JniDemo_nativeMethod (JNIEnv *env, jobject obj) { printf("native method in jni\n"); }
4. compile
编译只需要依赖 jni.h 的头文件,还有一个与OS相关的头文件,参考