美文网首页
Android开发之JNI基础知识

Android开发之JNI基础知识

作者: csong | 来源:发表于2017-03-20 15:39 被阅读115次

带着问题入场:

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

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

  1. 什么是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环境下。
  2. JNI提供了哪些基本数据类型,提供了哪些API?

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

      basic_type_sign.png
    • JNI引用类型与Java数据类型的对应关系

      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() 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
      • 方法的描述符

method_descriptor.png
  • JNI Exception

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

    • 首先使用ExceptionOccured()函数判断是否发生异常,如果发生异常,可以在JNI处理也可以通过ThrowNew将异常抛出到Java层处理。

相关文章

网友评论

      本文标题:Android开发之JNI基础知识

      本文链接:https://www.haomeiwen.com/subject/widdnttx.html