Android JNI NDK开发教程:JNI NDK概述《一》

2018-01-03  本文已影响0人  WrapOnly

简介

最近项目中经常使用到JNI,在这里记录总结一下。

JNI是什么?

        JNI(Java Native Interface)译为JAVA本地接口调用,它允许Java代码和其他语言(主要是C与C++)写的代码进行交互,简单的说,一种在Java虚拟机控制下执行代码的标准机制。

NDK是什么?

        Android NDK(Android Native Development Kit )是一套android本地开发工具集合,允许你用像C与C++语言那样实现应用程序的一部分。

为什么要使用NDK开发?

        1、安全性,java是半解释型语言,很容易被反汇编后拿到源代码文件,我们可以在重要的交互功能使用C或C++语言代替。

        2、效率,C或C++语言比起java来说效率要高出很多。

JNI和NDK的区别?

        从工具上说,NDK其实多了一个把.so和.apk打包的工具,而JNI开发并没有打包,只是把.so文件放到文件系统的特定位置上面。

        从编译库说,NDK开发C或C++只能能使用NDK自带的有限的头文件,而使用JNI则可以使用文件系统中带的头文件。

        从编写方式说,它们一样。

JNI 相关元素

1、JNI组织结构

        JNI函数表的组成就像C++的虚函数表,虚拟机可以运行多张函数表。JNI接口指针仅在当前线程中起作用,指针不能从一个线程进入另一个线程,但可以在不同的线程中调用本地方法。

2、原始数据

3、Java类型和JNI类型对应表

Java类型和JNI类型对应表

4、JNI域描述符

引用类型则为 L + 该类型类描述符 + 。

数组,其为 : [ + 其类型的域描述符 + 。

多维数组则是 n个[ +该类型的域描述符 , N代表的是几维数组。

String类型的域描述符为 Ljava/lang/String;[ + 其类型的域描述符 + ;int[ ] 其描述符为[Ifloat[ ] 其描述符为[FString[ ] 其描述符为[Ljava/lang/String;Object[ ]类型的域描述符为[Ljava/lang/Object;int [ ][ ] 其描述符为[[Ifloat[ ][ ] 其描述符为[[F

将参数类型的域描述符按照申明顺序放入一对括号中后跟返回值类型的域描述符,规则如下: (参数的域描述符的叠加)返回类型描述符。对于,没有返回值的,用V(表示void型)表示。

举例如下:

Java层方法 JNI函数签名String test ( ) Ljava/lang/String;int f (int i, Object object) (ILjava/lang/Object;)Ivoid set (byte[ ] bytes) ([B)V

JNIEnv与JavaVM 概念

1、JNIEnv 概念 : 是一个线程相关的结构体, 该结构体代表了 Java 在本线程的运行环境 ;

2、JNIEnv 与 JavaVM :

     注意区分这两个概念;

(1)JavaVM : JavaVM 是 Java虚拟机在 JNI 层的代表, JNI 全局只有一个;

(2)JNIEnv : JavaVM 在线程中的代表, 每个线程都有一个, JNI 中可能有很多个 JNIEnv;

3、JNIEnv 作用 :

(1)调用 Java 函数 : JNIEnv 代表 Java 运行环境, 可以使用 JNIEnv 调用 Java 中的代码;

(2)操作 Java 对象 : Java 对象传入 JNI 层就是 Jobject 对象, 需要使用 JNIEnv 来操作这个 Java 对象;

4、JNIEnv 体系结构

线程相关 : JNIEnv 是线程相关的, 即 在 每个线程中 都有一个 JNIEnv 指针, 每个JNIEnv 都是线程专有的, 其它线程不能使用本线程中的 JNIEnv, 线程 A 不能调用 线程 B 的 JNIEnv;

5、JNIEnv 不能跨线程 :

(1) 当前线程有效 : JNIEnv 只在当前线程有效, JNIEnv 不能在 线程之间进行传递, 在同一个线程中, 多次调用 JNI层方法, 传入的 JNIEnv 是相同的;

(2) 本地方法匹配多JNIEnv : 在 Java 层定义的本地方法, 可以在不同的线程调用, 因此 可以接受不同的 JNIEnv;

JNIEnv 结构 : 由上面的代码可以得出, JNIEnv 是一个指针, 指向一个线程相关的结构, 线程相关结构指向 JNI 函数指针 数组, 这个数组中存放了大量的 JNI 函数指针, 这些指针指向了具体的 JNI 函数;

注意:JNIEnv只在当前线程中有效。本地方法不能将JNIEnv从一个线程传递到另一个线程中。相同的 Java 线程中对本地方法多次调用时,传递给该本地方法的JNIEnv是相同的。但是,一个本地方法可被不同的 Java 线程所调用,因此可以接受不同的 JNIEnv。

更多经验持续更新...

上一篇下一篇

猜你喜欢

热点阅读