Android JNI Java构造方法的实例化和引用类型

首先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; // 堆 必须释放
}
发布了446 篇原创文章 · 获赞 67 · 访问量 24万+

猜你喜欢

转载自blog.csdn.net/hongxue8888/article/details/105127931
今日推荐