首先Dog类,添加构造方法,使构造方法被C++中直接实例化
添加两个按钮
在MainActivity中定义两个native方法testDog和testUnDog,两个按钮点击分别调用这两个方法
全局引用 和 构造方法实例化:
使用NewGlobalRef来定义dogClass为全局引用。如果不设置为全局引用,会隐式释放 dogClass , dogClass不为NULL 但 悬空,所以再次点击“测试引用”按钮就会报错。
全局引用必须手动释放,最后设置dogClass = NULL
// TODO 引用类型 + Java构造方法的实例化
jclass dogClass;
extern "C"
JNIEXPORT void JNICALL
Java_com_hongx_jni_MainActivity_testDog(JNIEnv *env, jobject thiz) {
// 局部引用:如果在函数里面,是在栈区,不用回收,函数结束,会自动回收 ,为了专业性,最好要写回收
if (dogClass == NULL) { // 第一次满足, 第二次不满足了
// 局部引用的方式
// const char * dog_class_str = "com/hongx/jni/Dog";
// dogClass = env->FindClass(dog_class_str);
// 解决各个局部引用带来的问题,全局引用(自己来提升)
const char *dog_class_str = "com/hongx/jni/Dog";
jclass temp = env->FindClass(dog_class_str);
dogClass = static_cast<jclass>(env->NewGlobalRef(temp));
// 手动释放全局引用之后,再次点击,没有进来
__android_log_print(ANDROID_LOG_DEBUG, "Dog", "dogClass == NULL");
}
// Java构造方法的实例化
const char *sig = "()V";
const char *method = "<init>"; // Java构造方法的标识
jmethodID init = env->GetMethodID(dogClass, method, sig);
env->NewObject(dogClass, init); // 由于dogClass 是悬空的,直接报错
// 会隐式释放 dogClass , dogClass不为NULL, 悬空 同时手动全局释放一致
}
extern "C"
JNIEXPORT void JNICALL
Java_com_hongx_jni_MainActivity_testUnDog(JNIEnv *env, jobject thiz) {
if (dogClass != NULL) {
__android_log_print(ANDROID_LOG_DEBUG, "Dog", "全局应用被释放了,上面的按钮不能点击了,否则报错");
env->DeleteGlobalRef(dogClass);
dogClass = NULL;
}
// Studnet * student = new Student; // 堆 必须释放
}