JNI
简介
JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通讯(主要是C&C++)。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他编程语言,只要调用约定受支持就可以。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的。例如,使用一些旧的库与硬件、操作系统进行交互,或者为了提供程序的性能。
使用流程
1 | JNIExport jstring JNICALL Java_com_example_hellojni_MainActivity_stringFromJNI( JNIEnv* env,jobject thiz ) |
jstring 是返回值类型Java_com_example_hellojni 是包名MainActivity 是类名stringFromJNI 是方法名
其中JNIExport和JNICALL是固定保留的关键字不要修改
JNI开发流程的步骤:
- 第1步:在Java中先声明一个native方法
- 第2步:编译Java源文件javac得到.class文件
- 第3步:通过javah -jni命令导出JNI的.h头文件
- 第4步:使用Java需要交互的本地代码,实现在Java中声明的Native方法(如果Java需要与C++交互,那么就用C++实现Java的Native方法。)
- 第5步:将本地代码编译成动态库(Windows系统下是.dll文件,如果是Linux系统下是.so文件,如果是Mac系统下是.jnilib)
- 第6步:通过Java命令执行Java程序,最终实现Java调用本地代码。
JNA
简介
JNA(Java Native Access)提供一组Java工具类用于在运行期间动态访问系统本地库而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口道native function的映射。
项目地址
https://github.com/java-native-access/jna
使用流程
JNA开发流程的步骤:
引用JNA相关的jar包和so库
实现一个动态库,通JNI步骤
创建Library,成功实现Java调用C/C++函数代码库
1
2
3
4
5
6
7
8
9
10
11
12
13
14import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
//继承Library,用于加载库文件
public interface Clibrary extends Library {
//加载libhello.so链接库
Clibrary INSTANTCE = (Clibrary) Native.loadLibrary("sayhello", Clibrary.class);
//此方法为链接库中的方法
int sayHello();
}
以上代码继承自Library 或StdCallLibrary,默认的是继承Library ,如果动态链接库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary,比如众所周知的kernel32库
接口内部需要一个公共静态常量:INSTANCE,通过这个常量,就可以获得这个接口的实例,从而使用接口的方法,也就是调用外部dll/so的函数。
- 调用实现接口
1 | int result = Clibrary.INSTANTCE.sayHello(); |
比较
JNA是建立在JNI技术基础之上的一个框架。使用JNI技术,不仅可以实现Java访问C函数,也可以实现C语言调用Java代码。而JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,你还是需要使用JNI技术。