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 )
如上面的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);
}
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);
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);
参考这篇博客找到的问题