Android NDK开发三 JNI基础
来源:互联网 发布:获取windows 7密钥 编辑:程序博客网 时间:2024/06/05 05:02
1 JNI 概念
JNI 全称 Java Native Interface,Java 本地化接口,可以通过 JNI 调用系统提供的 API。操作系统,无论是 Linux,Windows 还是 Mac OS,或者一些汇编语言写的底层硬件驱动都是 C/C++ 写的。因此通过JNI就可以调用这些底层的API。JNI 可以说是 C /C++语言和 Java 语言交流的适配器、中间件,下面我们来看看JNI调用示意图
一般在开发中,我们用JNI主要是调用C/C++ 编写的so库,及一般用于java c/c++混合编程
2 JNI 与Android NDK
1.JNI 与 NDK 区别
JNI: JNI是一套编程接口,用来实现Java代码与本地的C/C++代码进行交互;
NDK: NDK是Google开发的一套开发和编译工具集,可以生成动态链接库,主要用于Android的JNI开发;
2.JNI在Android中作用
JNI可以调用本地代码库(即C/C++代码),并通过 Dalvik 虚拟机与应用层和应用框架层进行交互,Android中JNI代码主要位于应用层和应用框架层;
应用层: 该层是由JNI开发,主要使用标准JNI编程模型;
应用框架层: 使用的是Android中自定义的一套JNI编程模型,该自定义的JNI编程模型弥补了标准JNI编程模型的不足;
3 JNI 数据类型
jni.h 头文件是为了让 C/C++ 类型和 Java 原始类型相匹配的头文件
由jni.h 头文件知道,jni.h有很多类型预编译的定义,并且区分了 C 和 C++的不同环境。
#ifdef HAVE_INTTYPES_H# include <inttypes.h> /* C99 */typedef uint8_t jboolean; /* unsigned 8 bits */typedef int8_t jbyte; /* signed 8 bits */typedef uint16_t jchar; /* unsigned 16 bits */typedef int16_t jshort; /* signed 16 bits */typedef int32_t jint; /* signed 32 bits */typedef int64_t jlong; /* signed 64 bits */typedef float jfloat; /* 32-bit IEEE 754 */typedef double jdouble; /* 64-bit IEEE 754 */#elsetypedef unsigned char jboolean; /* unsigned 8 bits */typedef signed char jbyte; /* signed 8 bits */typedef unsigned short jchar; /* unsigned 16 bits */typedef short jshort; /* signed 16 bits */typedef int jint; /* signed 32 bits */typedef long long jlong; /* signed 64 bits */typedef float jfloat; /* 32-bit IEEE 754 */typedef double jdouble; /* 64-bit IEEE 754 */#endif/* "cardinal indices and sizes" */typedef jint jsize;#ifdef __cplusplus/* * Reference types, in C++ */class _jobject {};class _jclass : public _jobject {};class _jstring : public _jobject {};class _jarray : public _jobject {};class _jobjectArray : public _jarray {};class _jbooleanArray : public _jarray {};//……typedef _jobject* jobject;typedef _jclass* jclass;typedef _jstring* jstring;typedef _jarray* jarray;typedef _jobjectArray* jobjectArray;typedef _jbooleanArray* jbooleanArray;//……#else /* not __cplusplus *//* * Reference types, in C. */typedef void* jobject;typedef jobject jclass;typedef jobject jstring;typedef jobject jarray;typedef jarray jobjectArray;typedef jarray jbooleanArray;//……#endif
当是C++环境时,jobject, jclass, jstring, jarray 等都是继承自_jobject类,而在 C 语言环境是,则它的本质都是空类型指针typedef void* jobject;
1 基本数据类型
下图是Java基本数据类型和本地类型的映射关系,这些基本数据类型都是可以直接在 Native 层直接使用的
2 引用数据类型
需要注意的是,在native层我们无法直接使用java对象,需要进行转化
1)引用类型不能直接在 Native 层使用,需要根据 JNI 函数进行类型的转化后,才能使用;一般转化为Jobject 或者jclass
2)多维数组(含二维数组)都是引用类型,需要使用 jobjectArray 类型存取其值;
例如,二维整型数组就是指向一位数组的数组,其声明使用方式如下:
//获得一维数组的类引用,即jintArray类型 jclass intArrayClass = env->FindClass("[I"); //构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为length,类型为 jsize jobjectArray obejctIntArray = env->NewObjectArray(length ,intArrayClass , NULL);
3 方法和变量 ID
在native层时,我们队java中的变量及方法也是无法直接使用的。当 Native 层需要调用 Java 的某个方法时,需要通过 JNI 函数获取它的 ID,根据 ID 调用 JNI 函数获取该方法;变量的获取也是类似。ID 的结构体如下:
struct _jfieldID; /* opaque structure */typedef struct _jfieldID* jfieldID; /* field IDs */struct _jmethodID; /* opaque structure */typedef struct _jmethodID* jmethodID; /* method IDs */
在使用java对象的变量或者方法时,一般有以下两步
1. 获取变量或者方法的id jfieldID或者jmethodID
jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*); jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
2 根据id调用java对象的变量或者方法
4 JNI 描述符
1域描述符
基本类型描述符:
下面是基本的数据类型的描述符,除了 boolean 和 long 类型分别是 Z 和 J 外,其他的描述符对应的都是Java类型名的大写首字母。另外,void 的描述符为 V
引用类型描述符
一般引用类型描述符的规则如下,注意不要丢 ;
L + 类描述符 + ;
String 类型的域描述符为:
Ljava/lang/String;
数组的域描述符特殊一点,如下,其中有多少级数组就有多少个“[”,数组的类型为类时,则有分号”;”,为基本类型时没有分号”;”
[ + 其类型的域描述符
下面举一些常见的类型的例子,例如:
int[] 描述符为 [Idouble[] 描述符为 [DString[] 描述符为 [Ljava/lang/String;Object[] 描述符为 [Ljava/lang/Object;int[][] 描述符为 [[Idouble[][] 描述符为 [[D
2 类描述符
类描述符是类的完整名称:包名+类名,java 中包名用 . 分割,jni 中改为用 / 分割
如,Java 中 java.lang.String 类的描述符为 java/lang/String
例:native 层获取 Java 的类对象,需要通过 FindClass() 函数获取, jni.h 的函数定义如下
//Cjclass (*FindClass)(JNIEnv*, const char*);//C++jclass FindClass(const char* name) { return functions->FindClass(this, name); }
字符串参数就是类的引用类型描述符,如 Java 对象 cn.cfanr.jni.JniTest,对应字符串为Lcn/cfanr/jni/JniTest; 如下:
jclass jclazz = env->FindClass("Lcn/cfanr/jni/JniTest;");
3 方法描述符
方法描述符需要将所有参数类型的域描述符按照声明顺序放入括号,然后再加上返回值类型的域描述符,其中没有参数时,不需要括号,如下规则:
(参数……)返回类型
Java 层方法 ——> JNI 函数签名String getString() ——> Ljava/lang/String;int sum(int a, int b) ——> (II)Ivoid main(String[] args) ——> ([Ljava/lang/String;)V
另外,对应在 jni.h 获取 Java 方法的 native 函数如下,其中 jclass 是获取到的类对象,name 是 Java 对应的方法名字,sig 就是上面说的方法描述符
//CjmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);//C++jmethodID GetMethodID(jclass clazz, const char* name, const char* sig) { return functions->GetMethodID(this, clazz, name, sig); }
不过在实际编程中,如果使用 javah 工具来生成对应的 native 代码,就不需要手动编写对应的类型转换了。
有关JNI的基础就介绍到这里了,下一篇将介绍JNI的高级知识,例如 JNIEnv,JNI中方法注册的方式,JNI调用java对象变量及方法
参考:
http://www.jianshu.com/p/ac00d59993aa
JNI开发系列①JNI概念及开发流程 - 简书
JNI 数据类型映射、域描述符说明 - qinjuning - CSDN博客
Android JNI 之 JNIEnv 解析 - 韩曙亮 - CSDN博客
Android 开发 之 JNI入门 - NDK从入门到精通 -韩曙亮 - CSDN博客
JNI 两种注册过程实战 - Android - 掘金
Andoid NDK编程 注册native函数 // Coding Life
- Android NDK开发三 JNI基础
- Android Studio中JNI NDK开发(三)
- Android NDK开发:JNI基础篇
- JNI/NDK基础开发
- Android Stuido Ndk-Jni 开发(三):Jni基本语法
- Android-NDK开发之基础--Android JNI实例代码(三)-- 在JNI中构造和实例化Java类
- Android-NDK开发之基础--Android JNI实例代码(三)-- 在JNI中构造和实例化Java类
- Android-NDK开发之基础--Android JNI实例代码(三)-- 在JNI中构造和实例化Java类
- Android JNI/NDK 开发
- 【Android 系统开发】Android JNI/NDK (三) 之 JNIEnv 解析
- Android NDK 开发教程三:Hello JNI 示例
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- Android-NDK开发之基础--Android JNI开发高级篇(JNI中的常用方法)
- linunx centos 6.5 安装redis 和ngnix
- fabric 部署 python web 应用的基本config
- elasticsearch集群快速上手搭建
- ExtJS 4.2 创建带复选框的树,并且有全选反选功能
- java并发编程学习4--forkJoin
- Android NDK开发三 JNI基础
- vue-resource和php跨域
- Android 使用jni校验应用签名sha1值,防止so文件逆向盗用
- Sift算子特征点提取、描述及匹配全流程解析
- constructor的使用 : 查看对象的构造函数
- coridc求atandmatlab仿真
- editText控件相关
- caffe学习 绘制loss和accuracy
- HDU-5882-Balanced Game 【奇偶】