美文网首页
jni反射java方法

jni反射java方法

作者: leaflying | 来源:发表于2020-12-24 13:19 被阅读0次

    在我们写Android代码时,调用一个类中没有公开的方法,可以进行反射调用,而JNI开发中C++调用java的方法也是反射调用。下面我们就了解一下通过jni中的c++调用java中的方法。

    1.类似于我们java中进行反射调用一下,我们得拿到我们的字节码对象
    2.通过字节码对象找到方法对象
    3.通过对象调用方法,可以调用空参数方法,也可以调用有参数方法,并且将参数通过调用的方法传入,(这里需要将参数变成java对象后才能传入,比如说如果我们要传递一个char *,那么我们需要把它转化为jstring对象)

    基本数据类型对应表

    Java类型 本地类型 描述
    boolean jboolean C/C++8位整型
    byte jbyte C/C++带符号的8位整型
    char jchar C/C++无符号的16位整型
    short jshort C/C++带符号的16位整型
    int jint C/C++带符号的32位整型
    long jlong C/C++带符号的64位整型
    float jfloat C/C++32位浮点型
    double jdouble C/C++64位浮点型
    Object jobject 任何Java对象,或者没有对应java类型的对象
    Class jclass Class对象
    String jstring 字符串对象
    Object[] jobjectArray 任何对象的数组
    boolean[] jbooleanArray 布尔型数组
    byte[] jbyteArray 比特型数组
    char[] jcharArray 字符型数组
    short[] jshortArray 短整型数组
    int[] jintArray 整型数组
    long[] jlongArray 长整型数组
    float[] jfloatArray 浮点型数组
    double[] jdoubleArray 双浮点型数组

    下面我们就开始写代码,首先拿class对象

    //可以通过传入全类名进行查找,注意这里需要把.替换成/
    jclass _jclass = env->FindClass("com/test/ndktestapplication/TestBean");
    
    //也可以在已有的对象中获取class对象
    jclass _jclass = env -> GetObjectClass(test_bean);
    

    然后我们通过class对象获取到方法ID,这里我们通过GetMethodID这个方法去获取,这里有三个参数 :第1个参数:Java类对象;第2个参数:方法名;第3个参数:该方法的签名。关于方法签名,下面提供一份表格。

    Java类型 签名
    boolean Z
    short S
    float F
    byte B
    int I
    double D
    char C
    long J
    void V
    引用类型 L + 全限定名 + ;
    数组 [+类型签名
    //获取构造方法的方法ID,注意构造方法的方法名是"<init>"
    jmethodID method_id = env->GetMethodID(_jclass, "<init>","()V");
    //获取普通方法的方法ID,注意"()"中是传入参数的参数类型,外面是返回值的类型
    jmethodID set_age_id = env->GetMethodID(_jclass,"setAge", "(I)V");
    

    然后调用方法

        jclass _jclass = env->FindClass("com/test/ndktestapplication/TestBean");
    
        jmethodID method_id = env->GetMethodID(_jclass, "<init>","()V");
    
        #调用构造方法创建对象
        jobject o = env->NewObject(_jclass, method_id);
    
        jmethodID set_name_id = env->GetMethodID(_jclass,"setName", "(Ljava/lang/String;)V");
        env->CallVoidMethod(o,set_name_id,name_);
    
        jmethodID set_age_id = env->GetMethodID(_jclass,"setAge", "(I)V");
        env->CallVoidMethod(o,set_age_id,age);
    
        env -> ReleaseStringUTFChars(name_,name);
        env -> DeleteLocalRef(_jclass);
    
    

    上面使用的java类

    public class TestBean {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
    

    如果java对象是通过java传递过来的,那么我们可以这么使用

        jclass _jclass = env -> GetObjectClass(test_bean);
    
        jmethodID get_name_id = env->GetMethodID(_jclass, "getName","()Ljava/lang/String;");
        jstring s = static_cast<jstring>(env->CallObjectMethod(test_bean, get_name_id));
    
        const char* name = env->GetStringUTFChars(s,0);
    

    这里需要我们注意的是,所有我们在这里创建的对象,如果不返回java,必须用release掉,否则内存泄露。包括NewStringUTF,NewObject。如果返回java不必release,java会自己回收。

    相关文章

      网友评论

          本文标题:jni反射java方法

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