带着问题入场:
- 什么是JNI,NDK, 与Java是什么关系,有什么应用场景?
- JNI提供了哪些基本数据类型?
接下来会针对这两个问题,一一道来。
-
什么是JNI, NDK, 有什么应用场景?
-
JNI是Oracle提供的用于Java调用C/C++或C/C++调用的一套机制, 有自己的一套API,并且与C/C++或者汇编混合使用JNI,Java Native Interface,是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code;在 native code 中嵌入 Java 虚拟机调用 Java 的代码。
-
NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的.
-
NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出"哪些文件需要编译"、"编译特性要求"等),就可以创建出so.
-
NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作.
-
应用场景:
- 可以将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率
- 可以将需要保密的应用逻辑使用C开发。毕竟,Java包都是可以反编译的
- 复用之前C/C++语言开发的基础功能模块到Android环境下。
-
-
JNI提供了哪些基本数据类型,提供了哪些API?
-
JNI基本数据类型与Java数据类型的对应关系
basic_type_sign.png -
JNI引用类型与Java数据类型的对应关系
reference_type.png -
提供的特有的类, jfieldID, jmethodID, JNIEnv等
-
jfielID 是JNI提供的JNI 字段类
-
jmethodID 是JNI提供的JNI方法类
-
JNIEnv是JNI 接口的全局指针类,类似于JNI的上下文对象
-
-
Global and Local References
为啥会用到这两类引用?先说LocalReference,比如平时通过New操作得到的引用类型的对象,都属于Local Reference,看上去像是一个局部变量,其实不是,它与局部变量有这本质区别,在用完变量后需要手动释放,而局部变量却不需要。
Global Reference 是全局的引用,在New Global后一定要Release 这个歌全局引用。
关于这两类引用的使用过程中的如何进行内存管理,在"JNI内存管理模型”中会详细描述。
-
提供哪几类API,作用分别是什么?
-- 类操作 FindClass()
-- 全局引用于局部引用相关NewGlobalRef() DeleteGlobalRef() NewWeakGlobalRef() DeleteWeakGlobalRef() NewLocalRef() DeleteLocalRef()
-- 对象操作 不知道有什么用?
-- 访问对象的成员
GetFieldID() Get<type>Field() 先拿fieldID,在获取字段值
Set<type>Field()-- 访问静态成员
GetStaticFieldID()
GetStatic<type>Fiel SetStatic<type>Field
-- 对象成员函数调用
GetMethodID()
Call<type>Method
Call<type>MethodA
Call<type>MethodV
CallNonvirtual<type>Method
CallNonvirtual<type>MethodA
CallNonvirtual<type>MethodV
-- 静态函数调用
GetStaticMethodID()
CallStatic<type>Method
CallStatic<type>MethodA
CallStatic<type>MethodV
-- 字符串操作
NewString() NewStringUTF()
GetStringLength()
GetStringChars()
ReleaseStringChars()
GetStringUTFLength()
GetStringUTFChars()
ReleaseStringUTFChars()
GetStringRegion()
GetStringUTFRegion()
-- 数组操作
GetArrayLength()
NewObjectArray(JNIEnv *env, jsize length,jclass elementClass, jobject initialElement);
jobject GetObjectArrayElement()
SetObjectArrayElement()基本数据类型的数组操作 New<PrimitiveType>Array() Get<PrimitiveType>ArrayElements() Release<PrimitiveType>ArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode) 参数对应关系图 void Get<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,jsize start, jsize len, NativeType *buf); void Set<PrimitiveType>ArrayRegion(JNIEnv *env, ArrayType array,jsize start, jsize len, const NativeType *buf)
-- 函数注册于反注册
jint RegisterNatives(JNIEnv *env, jclass clazz,const JNINativeMethod *methods, jint nMethods);
jint UnregisterNatives(JNIEnv *env, jclass clazz);
-- 反射函数 还不知道如何使用
jmethodID FromReflectedMethod(JNIEnv *env, jobject method);
jfieldID FromReflectedField(JNIEnv *env, jobject field);
jobject ToReflectedMethod(JNIEnv *env, jclass cls,jmethodID methodID, jboolean isStatic);
jobject ToReflectedField(JNIEnv *env, jclass cls,jfieldID fieldID, jboolean isStatic); -
JNI 类型签名
-
基本数据类型的类型签名
basic_type_sign.png-
引用数据类型的类型签名
reference_type_sign.png
-
-
方法的描述符
-
-
-
JNI Exception
-
三个函数ExceptionOccured(),ExceptionClear(),ThrownNew()。
-
首先使用ExceptionOccured()函数判断是否发生异常,如果发生异常,可以在JNI处理也可以通过ThrowNew将异常抛出到Java层处理。
-
网友评论