• Android JNI开发摘录(三)之JNI中的Java对象


          JNI中的Java对象

        Java本机接口提供了一个函数集来处理Java对象(使用方法/域)、句柄异常和用于线程的数据同步。这些函数在本机提供更好的访问Java对象的能力,允许用于更复杂的应用程序。这些函数的用法之一是被用来产生一个Java方法的回调,或者产生通信信息的回调。

         1.访问JNI中的域

         在Java类中有两种成员变量类型:静态域,它们属于类;非静态域,它们属于单个对象。为了可以访问一个域,必须向GetFieldID或GetStaticFieldID传递一个域描述符以及域的名称。域描述符是完整描述域类型的一个或多个字符。例如,域int的域描述符是I。用于数组的域描述符是以字符 [ 为前缀,用于数组的每一维。例如,int[]的域描述符是[I,int[][]的域描述符是[[I。对于引用类型,使用了类的完整限制符名称,但是点号被正斜杠替换,描述符将在开始被一个L,在结尾被一个分号所包围。例如,类型java.lang.Integer的域描述符是Ljava/lang/Integer。基本类型域描述符如下表:

    基本类型

    域描述符

    boolean

    Z

    byte

    B

    char

    C

    short

    S

    int

    I

    long

    J

    float

    F

    double

    D

           2.访问域的函数

           (1).下面的函数向指定域返回一个句柄,以便用于Get以及Set函数。GetObjectClass函数可以用来获取一个适合于该函数第一个参数的jclass。name是域的名称,sig是域描述符。如果函数失败,返回NULL:

    jfieldID GetFieldID(jclass clazz, const char *name, const char *sig);

         

          (2).下面的函数返回属于Java对象obj的,被fieldID指定的一个特定域:

    [NativeType] Get[Type]Field(jobject obj, jfieldID fieldID);

         (3).SetField函数将属于Java对象obj的,被fieldID指定的一个特定域的值设置为val:

    void Set[Type]Field(jobject obj,jfieldID fieldID, [NativeType] val);

        (4)GetStaticFieldID函数同GetFieldID函数功能相同,但它用于获取一个静态域的句柄:

    jfieldID GetStaticFieldID(jclass clazz,const char *name, const char *sig);



        (5)GetStaticField函数返回属于clazz描述的类,fieldID指定的一个静态域的值:

    [NativeType] GetStatic[Type]Field(jclass clazz,jfieldID fieldID);

        (6).SetStaticField函数设置属于clazz描述的类,fieldID指定一个静态域的值:

    void SetStatic[Type]Field(jclass clazz, jfieldID fieldID, [NativeType] value);

        3.使用JNI调用Java方法

        使用JNI可以调用Java中的静态及非静态方法,这时需要使用方法的名称和方法描述符来获得特定Java方法的句柄,然后才能通过CallMethod函数调用该Java方法。

        方法描述符通过将所有方法的参数类型放置到一个单一圆括号集中,然后在圆括号之后指定返回类型而形成。用于参数的类型以及返回类型使用在前面描述过的域描述符。如果方法返回void,则描述符就是V。若方法没有任何参数,则圆括号中为空。用于熟悉的main方法的方法描述符是([Ljava/lang/String;)V。如果希望调用构造函数,使用方法名<init>,对于静态构造函数,则使用<clinit>。

        JNI调用Java方法的步骤:

         获取方法和变量描述符的编译命令:javap -s -classpath . [PacketName+"."+Library Name]  如:javap -s -classpath . com.example.MyProject.MyLibrary

        (1).获取要调用方法所在的类:

    jclass GetObjectClass(jobject obj);

       (2).通过jclass获取要调用的方法的methodID,即方法句柄:

    /**

    *使用步骤(1)获取的jclass

    *方法名称

    *方法描述符

    */

    jmethod GetMethodID(jclass clazz,const char *name,const char *sig);

    jmethod GetStaticMethodID(jclass clazz,const char* name,const char *sig);

        (3).通过方法句柄调用方法,注意:如果希望调用一个构造函数或一个私有方法,方法ID将会基于实际对象的类获得,而不是基于对象的一个超类。

        

    /**

    *java环境传入的jobject

    *方法句柄

    */参数:接受大量参数,并将这些参数直接传送到Java方法中

    [NativeType] Call[Type]Method(jobject obj, jmethodID methodID,…);

    /**

    *该方法将参数列表作为一个va_list结构接受,该结构是随同参数列

    *表预包装的。

    */

    [NativeType] Call[Type]MethodV(jobject obj,jmethodID methodID,va_list args);

    /**

    *该方法将参数作为一个jvalue数组接受,它是可以使用任意本机数据*类型版本的Java数据类型形式的一个联合(union),包括jobject。

    */

    [NativeType] Call[Type]MethodA(jobject obj, jmethodID methodID, const jvalue *args);



    /**

    *下面三个方法也调用对象方法的一个实例,但是调用的Java方法是

    *基于jclass数的。这些函数可以在对象的层次结构中调用一个指定的方法,而不是仅仅基于对象的类调用一个方法。

    *jclass应通过传入要调用的方法所在的类的实例来获得。

    */

    [NativeType] CallNonvirtual[Type]Method(jobject obj, jclass clazz, jmethodID methodID, …);



    [NativeType] CallNonvirtual[Type]MethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);



    [NativeType] CallNonvirtual[Type]MethodA(jobject obj, jclass clazz, jmethodID methodID, const jvalue *args);





    /**

    *下面的函数调用属于传入的clazz类的一个静态方法。使用Get

    *StaticMethodID来获得方法句柄。

    */

    [NativeType] CallStatic[Type]Method(jclass clazz, jmethodID methodID, …);



    [NativeType] CallStatic[Type]MethodV(jclass clazz, jmethodID methodID, va_list args);



    [NativeType] CallStatic[Type]MethodA(jclass clazz, jmethodID methodID, const jvalue *args);
  • 相关阅读:
    从目标检测到图像分割简要发展史
    用卷积神经网络和自注意力机制实现QANet(问答网络)
    C# 监测每个方法的执行次数和占用时间(测试5)
    C# list常用的几个操作 改变list中某个元素的值 替换某一段数据
    C# 监测每个方法的执行次数和占用时间(测试4)
    生活 对最近工作 和 生活 感悟
    Cesium 加载天地图
    其它 开发常用工具
    PowerDesigner 画流程图
    RookeyFrame bin 目录
  • 原文地址:https://www.cnblogs.com/oxgen/p/2381018.html
Copyright © 2020-2023  润新知