What
首先解释下JNI是什么,Java Native Interface,Java本地化接口。众所周知Java是跨平台的语言,依托于不同平台的JVM运行。当Java需要和原生平台进行沟通时,这个时候就需要用道JNI,通过C/C++代码来实现Java的代码,这样Java就可以和原生代码(C/C++)进行相互调用了。
NDK: Native Develop Kit,是Android提供原生开发工具包。是为了更加方便JNI的开发,同时NDK里面还包含和交叉编译等工具。
Why
- Java毕竟依托于JVM,本质上jdk的核心代码中的核心实现也都是去通过JNI去调用系统的库。
- 原生代码相对于Java来说执行效率更高。同时核心实现Java完成不了的也是需要JNI。
- 原生代码进行编译生成的库,相对于Java的jar来说反编译难度更大,安全性更高。
- 便于移植
How
一个简单的JNI步骤
定义文件
1 | package com.test; |
javac
编译
1 | javac com/test/JniTest.java |
javah
生成头文件
1 | javah com.test.JniTest |
之后src
下会生成com_test_JniTest.h
文件,这里面就是我们即将写的C/C++代码的头文件了。
1 | /* DO NOT EDIT THIS FILE - it is machine generated */ |
里面就是包含了引用jni库
,方法声明
JNI结构
方法的命名形如:Java_com_test_JniTest_set
以Java+包名+类名+方法名,中间使用下划线进行隔开。
数据类型
基础类型
基本上在Java的基础类型的基础上加上小写的j即可,比如:
1 | int -> jint |
tips:这里只是将Java的数据类型映射到C++中,不可以和C++的类型进行混淆。
引用类型
普通对象
1 | Object -> jobject |
数组
1 | Object[] -> jobjectArray |
基本上以此类推
签名
C++调用Java
之前第一个步骤是Java调用C++,当然反过来也是可以的。既然我们在native方法中是会传入关于JVM环境,以及对象等。我们可以通过反射进行类加载,来调用方法。
Java文件有个方法
1 | public static void test(String str) { |
C++中
这里我们调用静态方法
1 | void call_java_method(JNIEnv *env, jobject thiz) |
调用普通普通方法
1 |