美文网首页
JNI中访问java成员变量和方法

JNI中访问java成员变量和方法

作者: tsia | 来源:发表于2019-07-13 17:44 被阅读0次
JNI中访问java对象和方法

访问成员变量

无论是实例变量还是静态变量,分三个步骤:

  1. 获取类。表示需要访问哪一个java类,如所在jni方法对应java实例方法,参数中有jobject对象,则需要通过GetObjectClass得到类;如所在jni方法对应java静态方法,参数中已有jclass对象。
  2. 获取域ID。表示要访问类中的哪个变量。
  3. 获取域值。即获取变量的值。

示例:java类中有实例变量和静态变量

public class MainActivity extends AppCompatActivity {

    private String instanceField = "instace";
    private static String staticField = "static field";
    ...
}

jni中获取时,GetFieldID方法的第二个参数为变量的名称,第三个参数为变量的签名描述符(见下文)

extern "C" JNIEXPORT void JNICALL
Java_smarttime_tsia_com_jnitest3_MainActivity_stringFromJNI(JNIEnv* env, jobject obj) {
    // 获取类
    jclass clazz = env->GetObjectClass(obj);

    // 获取实例变量ID
    jfieldID  instanceFieldId = env->GetFieldID(clazz, "instanceField", "Ljava/lang/String;");
    // 获取实例变量值
    jstring instanceValue = static_cast<jstring>(env->GetObjectField(obj, instanceFieldId));

    // 获取静态变量ID
    jfieldID staticField = env->GetStaticFieldID(clazz, "staticField", "Ljava/lang/String;");
    // 获取静态变量值
    jstring staticValue = static_cast<jstring>(env->GetStaticObjectField(clazz, staticField));
    ...
}
  1. 若域ID频繁使用,可以缓存下来以提高程序性能。
  2. 原生代码方位java变量需要调用两到三个jni函数,给程序增加了额外的负担,导致性能的下降。一般情况下,建议将所有需要的参数传递给原生方法调用。

访问成员方法

分三个步骤:

  1. 获取类。表示需要访问哪一个java类,如所在jni方法对应java实例方法,参数中有jobject对象,则需要通过GetObjectClass得到类;如所在jni方法对应java静态方法,参数中已有jclass对象。
  2. 获取方法ID。表示要访问类中的哪个方法
  3. 调用方法。

示例:java类中有实例方法和静态方法

public class MainActivity extends AppCompatActivity {
    ...
    private String instanceMethod() {
        return "instance method";
    }

    private static String staticMethod() {
        return "static method";
    }
    ...

现在jni中调用,并获得其返回值,GetMethodID第二个参数为方法名称,第三个参数为方法的签名描述符(见下文)

extern "C" JNIEXPORT void JNICALL
Java_smarttime_tsia_com_jnitest3_MainActivity_stringFromJNI3(JNIEnv* env, jobject obj) {

    // 获取类
    jclass clazz = env->GetObjectClass(obj);

    // 获取实例方法ID
    jmethodID instancemethodId = env->GetMethodID(clazz, "instanceMethod", "()Ljava/lang/String;");
    // 调用实例方法
    jstring instanceRet = static_cast<jstring>(env->CallObjectMethod(obj, instancemethodId));

    // 获取静态方法ID
    jmethodID staticmethodId = env->GetStaticMethodID(clazz, "staticMethod", "()Ljava/lang/String;");
    // 调用静态方法
    jstring staticRet = static_cast<jstring>(env->CallStaticObjectMethod(clazz, staticmethodId));
    ...
}
  1. 若方法ID频繁使用,可以缓存下来以提高程序性能。
  2. java和原生代码之间的转换代价较大,程序设计上要最小化在原生代码调用java方法,以提高程序的性能。

签名描述符

上文中使用到的签名描述符用来标识能标识变量的类型、方法的参数和返回值,获取描述符有两种方式:

命令生成方式

javap是JDK提供的命令行方式下java类文件的反编译程序,它可以从编译的类文件中解压缩变量和方法的描述符。

构建玩之后,到对应文件的.class目录下,比如MainActivity.class所在的目录下,执行 descriptor后面就是对应变量或方法的签名,可以直接复制使用。

非private的变量或方法才会显示描述符,若为private方法可先改成public/protected然后生成,其描述符是一样的。

手动书写

java基本类型和描述符对应表:

Java Language Type Field Desciptor
boolean Z
byte B
char C
short S
int I
long J
float F
double D
void V

对于引用类型,描述符是以"L"开头,";"结尾

Java Language Type Field Desciptor
String Ljava/lang/String;
Object[] [Ljava/lang/Object;

对于数组类型,使用"["和对应的类型描述符来表述,例

Java Langauage Type Descriptor
int[][] [[I
double[][] [[[D

方法描述符一般格式为:(参数desciptor)返回值desciptor,示例:

Java Language Method Method Descriptor
void fun(long v1, String v2, long v3) (JLjava/lang/String;J)V
String f(); ()Ljava/lang/String;
void fun(byte[] bytes); ([B)V

可以使用命令生成来验证手动写的是否正确。

相关文章

《JNI数组操作》
《使用CMake构建Android JNI工程》

相关文章

  • NDK-JNI访问Java变量和方法

    JNI访问Java成员变量 1.定义成员变量textStr 2.添加native方法accessField(): ...

  • JNI中访问java成员变量和方法

    访问成员变量 无论是实例变量还是静态变量,分三个步骤: 获取类。表示需要访问哪一个java类,如所在jni方法对应...

  • SharedPreferences、内外部存储

    java中规定,内部类只能访问外部类中的成员变量,不能访问方法中定义的变量,如果要访问方法中的变量,就要把方法中的...

  • 1.3 静态成员

    基本概念 java类中的成员(变量和方法)分为两类: 实例成员,必须通过对象实例去访问,对于实例变量,每个对象都有...

  • 2020-06-19this与super

    关键字访问成员变量访问构造方法访问成员方法thisthis.成员变量:访问本类的成员变量this(...):访问本...

  • Java中的继承

    学习笔记 目录:一、继承的实现二、继承中成员变量、构造方法、成员方法访问特点1、继承中成员变量访问的特点2、继承中...

  • 利用runtime访问苹果隐藏的成员变量和成员方法

    访问成员变量 访问成员方法

  • JAVA(三)回忆基础扫盲之一

    一.对象与类 简单的类 实例化构造方法 访问实例化变量和访问成员方法使用get和set方法 二.JAVA的数据类型

  • JavaSE语法(部分)

    JavaSE语法(部分) 继承 继承中变量的访问特点 在子类方法中访问一个变量/成员方法 子类局部范围找 子类成员...

  • java之了解

    访问实例变量和方法 通过已创建的对象来访问成员变量和成员方法,如下所示: /* 实例化对象*/ ObjectRef...

网友评论

      本文标题:JNI中访问java成员变量和方法

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