04.引用,异常处理,缓存策略

JNI 引用变量

引用类型:局部引用和全局引用
作用:在JNI中告知虚拟机何时回收一个JNI变量

局部引用

//局部引用
public native void localRef();

使用

//局部引用:
//通过DeleteLocalRef手动释放对象
//1.访问一个很大的java对象,使用完之后,还要进行复杂的耗时操作
//2.创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性
//这个时候都需要通过DeleteLocalRef手动释放掉对象
JNIEXPORT void JNICALL Java_com_gxl_JniTest_localRef
(JNIEnv *env, jobject jobj){
    for (int i = 0; i < 100; i++){
        //获取Date的class
        jclass cls=(*env)->FindClass(env, "java/util/Date");
        //获取Date的构造方法的id
        jmethodID cons_id=(*env)->GetMethodID(env, cls, "<init>", "()V");
        //创建Date对象
        jobject date=(*env)->NewObject(env, cls, cons_id);
        //。。。。。中间一些列操作

        //在操作完成后要进行释放,否则每次循环都会产生一个Date对象
        //不在使用jobject对象了
        //通知垃圾回收器回收这些对象
        (*env)->DeleteLocalRef(env,date);
    }
}

全局引用

//全局变量
//创建全局变量
public native void createGlobalRef();
//获取全局变量
public native String getGlobalRef();
//删除全局变量
public native void deleteGlobalRef();

使用

t.createGlobalRef();
String globalRef=t.getGlobalRef();
System.out.println("全局变量:"+globalRef);
t.deleteGlobalRef();

函数实现

//全局引用
//共享(可以跨多个线程),手动控制内存使用

jstring global_str;
//创建全局引用
JNIEXPORT void JNICALL Java_com_gxl_JniTest_createGlobalRef
(JNIEnv *env, jobject jobj){
    //这句话是乱码的,要想解决这个乱码看上次的string
    jstring str=(*env)->NewStringUTF(env, "c 的全局引用");
    global_str=(*env)->NewGlobalRef(env, str);
}
//获取全局引用
JNIEXPORT jstring JNICALL Java_com_gxl_JniTest_getGlobalRef
(JNIEnv *env, jobject jobj){
    return global_str;
}
//释放全局引用
JNIEXPORT void JNICALL Java_com_gxl_JniTest_deleteGlobalRef
(JNIEnv *env, jobject jobj){
    (*env)->DeleteGlobalRef(env,global_str);
}

弱全局引用

节省内存,在内存不足时可以是释放所引用的对象
可以引用一个不常用的对象,如果为NULL,临时创建
创建:NewWeakGlobalRef,销毁:DeleteGlobalWeakRef

异常

//异常
public String key="json";
public native void exception();

使用

try{
    //如果c中发生异常,会在这里直接崩溃,后面的不会运行
    t.exception();
}catch(Throwable e){
    //如果在c中发生异常通过Throwable可以捕捉到
    System.out.println("发生异常:"+e.getMessage());
}
System.out.println("发生异常之后");

函数实现

//异常处理
//1.保证Java代码可以运行
//2.补救措施保证C代码继续运行

//JNI自己抛出的异常,在Java层可以通过Throwable被捕捉,也可以在C层清空
//用户通过ThrowNew抛出的异常,可以在Java层捕捉
JNIEXPORT void JNICALL Java_com_gxl_JniTest_exception
(JNIEnv *env, jobject jobj){
    jclass cls=(*env)->GetObjectClass(env, jobj);
    //获取key2 获取不到会发生异常
    jfieldID fid=(*env)->GetFieldID(env, cls, "key2", "Ljava/lang/String;");
    //检测是否发生异常
    jthrowable throw=(*env)->ExceptionOccurred(env);
    if (throw != NULL){
        //如果有异常
        //让java代码可以继续运行
        //清楚异常
        (*env)->ExceptionClear(env);

        //补救措施
        fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
    }

    //获取key属性的值
    jstring value=(*env)->GetObjectField(env, jobj, fid);
    //将jstring 转成 char*
    char* c_value=(*env)->GetStringUTFChars(env, value, NULL);

    //判断key的值是不是 super json
    if (_stricmp(c_value, "super json") != 0){
        //将异常抛给java层去处理
        //找到异常类
        jclass excep=(*env)->FindClass(env, "java/lang/IllegalArgumentException");
        //抛出异常
        (*env)->ThrowNew(env, excep, "value is invalidate");
    }
}

缓存策略

这里的缓存是通过静态局部变量来实现的

//缓存策略
public native void cache();

使用

for(int i=0;i<100;i++){
    t.cache();
}

函数实现

//使用静态局部变量来缓存
JNIEXPORT void JNICALL Java_com_gxl_JniTest_cache
(JNIEnv * env, jobject jobj){
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //静态局部变量,每一次这次方法调用都会存在,在这个方法中是共享的。
    //这里使用static 局部变量无论调用多少次这个方法则只会打印一次
    static jfieldID key_id=NULL;
    //如果使用的是局部变量,调用多少次这个方法就会打印多少次
    //fieldID key_id = NULL;
    if (key_id == NULL){
        key_id = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
        printf("--------GetFieldID-------\n");
    }
}

全局变量

public native static void initIds();

使用

static{
    System.loadLibrary("jni_04");
    initId();
}

函数实现

//初始化全局变量,动态库加载完成之后,立刻缓存起来
jfieldID key_fid;
jmethodID random_mid;
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_initIds(JNIEnv *env, jclass jcls){
    key_fid = (*env)->GetFieldID(env, jcls, "key", "Ljava/lang/String;");
    random_mid = (*env)->GetMethodID(env, jcls, "genRandomInt", "(I)I");
}

猜你喜欢

转载自blog.csdn.net/a_thousand_miles/article/details/81125038