Android开发之JNI基础知识

带着问题入场:

  • 什么是JNI,NDK, 与Java是什么关系,有什么应用场景?
  • JNI提供了哪些基本数据类型?

接下来会针对这两个问题,一一道来。

  1. 什么是JNI, NDK, 有什么应用场景?

    • JNI是Oracle提供的用于Java调用C/C++或C/C++调用Java的一套机制, 有自己的一套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环境下。
  2. JNI提供了哪些基本数据类型,提供了哪些API?

    • JNI基本数据类型与Java数据类型的对应关系

      Android开发之JNI基础知识_第1张图片
      basic_type_sign.png
    • JNI引用类型与Java数据类型的对应关系

      Android开发之JNI基础知识_第2张图片
      reference_type.png
    • 提供的特有的类, jfieldID, jmethodID, JNIEnv等

      1. jfielID 是JNI提供的JNI 字段类

      2. jmethodID 是JNI提供的JNI方法类

      3. 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() GetField() 先拿fieldID,在获取字段值
      SetField()

      -- 访问静态成员
      GetStaticFieldID()
      GetStaticFiel SetStaticField
      -- 对象成员函数调用
      GetMethodID()
      CallMethod
      CallMethodA
      CallMethodV
      CallNonvirtualMethod
      CallNonvirtualMethodA
      CallNonvirtualMethodV
      -- 静态函数调用
      GetStaticMethodID()
      CallStaticMethod
      CallStaticMethodA
      CallStaticMethodV
      -- 字符串操作
      NewString() NewStringUTF()
      GetStringLength()
      GetStringChars()
      ReleaseStringChars()
      GetStringUTFLength()
      GetStringUTFChars()
      ReleaseStringUTFChars()
      GetStringRegion()
      GetStringUTFRegion()
      -- 数组操作
      GetArrayLength()
      NewObjectArray(JNIEnv *env, jsize length,jclass elementClass, jobject initialElement);
      jobject GetObjectArrayElement()
      SetObjectArrayElement()

       基本数据类型的数组操作
       NewArray()
       GetArrayElements()
       ReleaseArrayElements(JNIEnv *env, ArrayType array, NativeType *elems, jint mode)
       参数对应关系图
       
       void GetArrayRegion(JNIEnv *env, ArrayType array,jsize start, jsize len, NativeType *buf);
       void SetArrayRegion(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 类型签名

      • 基本数据类型的类型签名

        Android开发之JNI基础知识_第3张图片
        basic_type_sign.png
        • 引用数据类型的类型签名

          Android开发之JNI基础知识_第4张图片
          reference_type_sign.png
      • 方法的描述符

Android开发之JNI基础知识_第5张图片
method_descriptor.png
  • JNI Exception

    • 三个函数ExceptionOccured(),ExceptionClear(),ThrownNew()。

    • 首先使用ExceptionOccured()函数判断是否发生异常,如果发生异常,可以在JNI处理也可以通过ThrowNew将异常抛出到Java层处理。但是在实际的使用中发现JNI的Exception有兼容性问题,不推荐使用。

你可能感兴趣的:(Android开发之JNI基础知识)