JNI开发中引用的使用(五)


前言

Java中有强引用、软引用、弱引用,虚引用,在JNI的使用中有局部引用(Local Reference)、全局引用(Global Reference)、弱全局引用(Weak Global Reference),本文主要介绍JNI的引用的使用


在JNI开发中比较重要的就是对内存的管理,也就是对引用的使用,否则很容易出现内存溢出,野指针等问题。java中有gc机制可以自动回收内存,在C/C++中new了一个对象,在使用结束时需要Delete,malloc一次同样需要free一次。在C/C++中还分栈空间和堆空间,所有的自动变量、函数形参都存储在栈中,自动分配(申请方式如:int i[10]),变量离开作用域后自动释放,malloc和new 都是在堆空间中,由程序员手动分配和释放,可申请占系统内存的80%

1.局部引用

在Native方法中,经常使用FindClass()、GetMethodID()、GetFieldID()来获取jclass、jmethodID、jfieldID和通过NewLocalRef产生的都是局部变量,退出Native方法时销毁,也可以调用DeleteLocalRef主动释放,不在本地函数中跨函数使用,不能跨线前使用

	jclass  clazz=(*env)->FindClass(env, "java/lang/String");
    jmethodID jmID = (*env)->GetMethodID(env, clazz, "<init>","([BLjava/lang/String;)V");
    jcharArray charArr = (*env)->NewCharArray(env, 10);
    jstring str_obj = (*env)->NewObject(env, clazz, jmID, charArr);
    jstring str_local_ref = (*env)->NewLocalRef(env,str_obj);   // 通过NewLocalRef函数创建

2.全局引用

通过NewGlobalRef函数创建,会阻止gc回收所引用的对象,可以跨方法、跨线程使用。JVM不会自动释放,必须调用DeleteGlobalRef手动释放

///全局引用
static jclass string_clazz;
void fun_global_ref(JNIEnv *env, jobject obj){
    jclass cls_string = (*env)->FindClass(env, "java/lang/String");
    string_clazz = (*env)->NewGlobalRef(env,cls_string);// 通过NewGlobalRef函数创建
    (*env)->DeleteGlobalRef(env,string_clazz);//手动释放

}

3.弱全局引用

通过NewWeakGlobalRef函数创建,不会阻止gc回收所引用的对象,可以跨方法、跨线程使用。引用不会自动释放,在JVM认为应该回收它的时候(比如内存紧张的时候)进行回收而被释放。或调用DeleteWeakGlobalRef手动释放。

///全局弱引用
static jclass weak_string_clazz;
void fun_weak_global_ref(JNIEnv *env, jobject obj){
    jclass cls_string = (*env)->FindClass(env, "java/lang/String");
    weak_string_clazz = (*env)->NewWeakGlobalRef(env,cls_string);// 通过NewWeakGlobalRef函数创建
    (*env)->DeleteWeakGlobalRef(env,weak_string_clazz);//手动释放
}

4.野指针

“野指针”不是NULL指针,是指向“垃圾”内存的指针,if很容易判断是否是一个空指针,但是if无法判断一个指针是正常指针还是“野指针”
“野指针”形成的原因

  1. 指针变量没有被初始化
  2. 指针p被free或者delete之后,没有置为NULL,误以为p是个合法的指针
    下面是一个野指针的例子
///野指针
JNIEXPORT jstring JNICALL Java_clz_Register_testWildPointer(JNIEnv *env, jobject obj) {
    jcharArray elemArray;
    char *chars = "c";
    jstring j_str = NULL;
    static jclass clazz = NULL;
    static jmethodID cid_string = NULL;

    ///1 缓存clazz  错误的缓存
    if (clazz == NULL) {
        clazz = (*env)->FindClass(env, "java/lang/String");
        if (clazz == NULL) {
            return NULL;
        }
    }
    ///缓存String的构造方法ID
    if (cid_string == NULL) {
        cid_string = (*env)->GetMethodID(env, clazz, "<init>", "([C)V");
        if (cid_string == NULL) {
            return NULL;
        }
    }
    elemArray = (*env)->NewCharArray(env, strlen(chars));
    (*env)->SetCharArrayRegion(env, elemArray, 0, strlen(chars), (const jchar *) chars);
    j_str = (*env)->NewObject(env, clazz, cid_string, elemArray);
    (*env)->DeleteLocalRef(env, elemArray);
    (*env)->DeleteLocalRef(env, clazz);
    elemArray=NULL;
//    clazz=NULL;
    return j_str;

}

上面的代码在ja va中调用一次testWildPointer不会报错,当调用testWildPointer第二次时 就会报错,原因是第一次调用testWildPointer,DeleteLocalRef掉clazz后,clazz没有被置为NULL,就成了一个野指针,他是不为NULL的,所以并没有走FindClass获取,这里两种办法都可以报错,clazz==NULL或者变量声明的static关键字去掉


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shunsix

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值