ITPub博客

首页 > IT职业 > IT图书 > 初识Android NDK简介

初识Android NDK简介

IT图书 作者:boriszhang 时间:2021-09-09 10:00:47 0 删除 编辑

原文链接:http://www.apkbus.com/blog-705730-60952.html

I. 初识

1. NDK

Native Development Kit

是一套让你的Android应用一部分代码可以使用像C/C++语言的工具包

一般什么时候可以使用NDK

谷歌建议真正要使用NDK的情况是在很少数情况

  • 需要提高执行性能(e.g. 大数据排序)

  • 需要使用c/c++实现的第三方库(如 Ffmpeg,OpenCV)

  • 需要调用更加底层的代码(如,你想调用Dalvik以外的代码)

2. JNI

Java Native Interface

是一套在Java虚拟机控制下代码执行的标准机制。使得Java可以调用c/c++的方法,或者c/c++中可以调用Java。

JNI标准机制的实现

由汇编或c/c++的代码,组装(assembled)成动态库(允许非静态绑定),由此实现Java与c/c++双向调用。

JNI的优势

相比其他类似的(Netscape Java运行接口、Microsoft的原始本地接口、COM/Java接口)相比,它的优势在于兼容性:

  • 对二进制兼容(c/c++的代码编译后是二进制,由于二进制是程序兼容性类型(不用改变执行文件,就可以直接在不同环境下执行),所以c/c++编译后的代码可以在任何平台下执行)

  • 对所有用Java虚拟机的具体平台兼容

II. 基本知识

为了更清晰,本地(虚拟机所在环境原生语言(通常是c/c++))这里都用native单词表示,而不直译

参数与引用

1. 方法参数说明

虚拟机需要追踪所有传递到native层的参数,使得GC不会在native层还在用这些参数引用的时候被清除了

需要注意
  1. 原始类型直接通过相互拷贝传递

  2. 对象 通过引用传递

JNI原始类型
Java类型 Native类型 备注
boolean jboolean unsigned 8 bits
byte jbyte signed 8 bits
char jchar unsighned 16 bits
short jshort signed 16 bits
int jint signed 32 bits
long jlong signed 64 bits
float jfloat 32 bits
double jdouble 64 bits
void(指针/对象引用) void N/A

例子

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * @param *env JNI接口指针
 * @param obj 在native方法中定义的对象引用
 * @param i 原始类型 整数型
 * @param s 对象引用 string
 */
jdouble Java_pkg_Cls_f__ILjava_lang_String_2 (JNIEnv *env, jobject obj, jint i, jstring s)
{
     const char *str = (*env)->GetStringUTFChars(env, s, 0);
     (*env)->ReleaseStringUTFChars(env, s, str);
     return 10;
}

2. 其他引用类型说明

JNI定义了三种引用类型 局部引用、全局引用、全局弱引用

局部引用:

所有通过JNI方法返回的Java对象都是局部引用
局部引用只对创建该引用所在线程可见。

方法结束时释放。但是也可以调用JNI方法DeleteLocalRef对其马上进行释放。

全局引用

只有在主动调用释放方法时才释放,对其释放的JNI方法: DeleteGlobalRef; 创建全局引用的方法: NewGlobalRef

例子

1
2
3
4
5
6
7
8
9
10
11
jclass localClazz;
jclass globalClazz;

localClazz = (*env)->FindClass(env, "java/lang/String");
globalClazz = (*env)->NewGlobalRef(env, localClazz);

// 立即释放localClazz局部引用
(*env)->DeleteLocalRef(env, localClazz);

// 立即释放globalClazz全局引用
(*env)->DeleteGlobalRef(env, globalClazz);

错误机制

JNI不会像Java一样检测像NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException、ArrayStoreException等这样的错误。

不报错原因
  1. 错误检测会导致性能下降

  2. 在大多数C库函数中,很难对错误进行处理

处理方式

JNI允许使用Java的异常处理

处理JNI函数中对应的出错的代码(因为即使出现异常, JNI层只会返回错误码,自己并不会报异常), 然后在JNI函数中错误对象抛异常到Java层(根据返回的错误代码)。

1
2
// 如果是一些数组操作的异常,可以使用ArrayIndexOutOfBoundsException、ArrayStoreException
jthrowable ExceptionOccurred(JNIEnv *env);

JNI的编码

标准UTF-8主要用在C,而Java使用的是UTF-16
JNI 使用的是 修改过的UTF-8: Modified UTF-8 Strings

结果:

被编码过的’修改过的UTF-8’字符串只包含非空ASCII字符串,其中每个字符只需一个字符就可表示。但是所有的Unicode字符串都可以被表示

与标准UTF-8的差别
  1. null字符(0)使用两个字节的格式而非一个字节进行编码,因为修改过的UTF-8不再有嵌入的null(

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/2435/viewspace-2815164/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-08-16

  • 博文量
    110
  • 访问量
    1069