JNI基础学习-jni调用java原生方法

public class Person {

    private void setStudent(Student student){
        Log.d("dsh", "setStudent: "+student.toString());
    }
}
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    @Override
    public String toString() {
        return "Student{name='" + name + '\'' +", age=" + age +'}';
    }
}

调用java方法有四个很重要的东西,class、methodID、sig(签名)、实例对象。
class:自然不必说就是类信息
methodID:就是方法信息
sig:就是方法签名,里面包括了方法的参数类型信息 和返回信息。如(Ljava/lang/String;)V 代表的就是 void xxx(String)方法;其中构造方法用 ,多个参数的方法这样表示 (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; 代表 String xxxx(String , String )

调用普通java方法

如上面的Person 和Student两个类,我们设计一个传入 姓名 和年龄,最后调用Person.setStudent方法。

extern "C"
JNIEXPORT void JNICALL
Java_com_example_ndk_1jni_102_MainActivity_testObject2(JNIEnv *env, jobject thiz, jstring name,
                                                       jint age) {

    //创建Student对象
    const char  * student_class_str = "com/example/ndk_jni_02/Student";
    jclass student_class = env->FindClass(student_class_str);
    jobject student_obj = env->AllocObject(student_class);
    //调用setName
    jmethodID setName_ID = env->GetMethodID(student_class,"setName","(Ljava/lang/String;)V");
    env->CallVoidMethod(student_obj,setName_ID,name);
    //调用setAge
    jmethodID setAge_ID = env->GetMethodID(student_class,"setAge","(I)V");
    env->CallVoidMethod(student_obj,setAge_ID,age);
    
    //创建Person对象
    const char * person_class_str = "com/example/ndk_jni_02/Person";
    jclass person_class = env->FindClass(person_class_str);
    jobject person_obj = env->AllocObject(person_class);

    //调用Person的setStudent
    jmethodID setStudent_ID = env->GetMethodID(person_class,"setStudent","(Lcom/example/ndk_jni_02/Student;)V");
    env->CallVoidMethod(person_obj,setStudent_ID,student_obj2);
}

调用java的构造方法 和多个参数情况

NewObject 和 AllocObject 前者是调用指定的构造方法创建对象,后者是仅仅构建一个新的类对象(仅仅为类对象分配内存空间而已),不初始成员变量,也不调用构造方法。

    const char  * student_class_str = "com/example/ndk_jni_02/Student";
    jclass student_class = env->FindClass(student_class_str);
	jmethodID student_ID = env->GetMethodID(student_class,"","(Ljava/lang/String;I)V");
	jobject student_obj2 = env->NewObject(student_class,student_ID,name,age);

调用java的静态方法


public class Person {
	//省略。。。。

    public static String getStudentName(Student student){
        Log.d("dsh","student name = "+student.getName());
        return student.getName();
    }
}

	//省略一些代码,可以在前面找到这个方法创建
    jmethodID getStudentName_ID = env->GetStaticMethodID(person_class,"getStudentName","(Lcom/example/ndk_jni_02/Student;)Ljava/lang/String;");

    jstring string_obj = static_cast<jstring>(env->CallStaticObjectMethod(person_class,
                                                                          getStudentName_ID,
                                                                          student_obj2));
    const char *stringChar = env->GetStringUTFChars(string_obj,0);
    LOGD("jni name is %s",stringChar);

出现一个结果全部打印,但是报错错误信息

2020-04-29 21:36:38.622 24322-24322/? A/DEBUG: pid: 24280, tid: 24280, name: mple.ndk_jni_02  >>> com.example.ndk_jni_02 <<<
2020-04-29 21:36:38.622 24322-24322/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xa1
2020-04-29 21:36:38.623 24322-24322/? A/DEBUG: Cause: null pointer dereference

原因是没有回收对象,env->ReleaseStringUTFChars(string_obj,stringChar);

参考这篇博客找到的问题

你可能感兴趣的:(android)