JNI笔记 JNI引用,异常处理,初始化成员变量
来源:互联网 发布:男士衣服搭配 知乎 编辑:程序博客网 时间:2024/06/08 17:49
1 回收局部引用变量
局部引用,通过DeleteLOcalREf手动释放对象
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_localRef(JNIEnv *env, jobject jobj){ int i = 0; //模拟:循环创建对象 for (;i<5;i++){ jclass cls = (*env)->FindClass(env,"java/util/Date"); jmethodID constructor_mid = (*env)->GetMethodID(env,cls,"<init>","()V"); //创建Date对象 jobject obj = (*env)->NewObject(env, cls, constructor_mid); //不在使用jobject对象了 //通知垃圾回收期回收这些对象 (*env)->DeleteLocalRef(env,obj); }}
java代码
JniTest jniTest = new JniTest();public static void main(String[] args) { JniTest jniTest = new JniTest(); jniTest.localRef(); }
使用场景
- 访问一个较大的java对象,使用完了之后,还要进行复杂的耗时操作
- 创建了大量的局部引用,占用了太多的内存,而且这些局部引用跟后面的操作没有关联性
2 回收局部引用变量
c代码
jstring global_str;//创建JNIEXPORT void JNICALL Java_com_yeliang_JniTest_createGlobalRef(JNIEnv *env, jobject jobj){ jstring obj = (*env)->NewStringUTF(env,"russul westbruk is so powerful!"); global_str = (*env)->NewGlobalRef(env,obj);}//获得JNIEXPORT void JNICALL Java_com_yeliang_JniTest_getGlobalRef(JNIEnv *env, jobject jobj){ return global_str;}//释放JNIEXPORT void JNICALL Java_com_yeliang_JniTest_deleteGlobalRef(JNIEnv *env, jobject jobj){ (*env)->DeleteGlobalRef(env,global_str);}
java代码
public native void createGlobalRef();public native String getGlobalRef();public native void deleteGlobalRef();public static void main(String[] args) { JniTest jniTest = new JniTest(); jniTest.createGlobalRef(); System.out.println(jniTest.getGlobalRef()); jniTest.deleteGlobalRef(); }
打印结果
russul westbruk is so powerful!
3 异常处理
- 保证Java代码可以运行
- 补救措施保证C代码继续运行
- JNI自己抛出的异常,在Java层无法捕捉,只能在C层清空
- 用户通过TrowNew抛出的异常,可以在Java层捕捉
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_exception(JNIEnv *env, jobject jobj){ jclass cls = (*env)->GetObjectClass(env,jobj); jfieldID fid = (*env)->GetFieldID(env,cls,"aa","Ljava/lang/String");}
成员变量里的名字为field但是我这里写成了aa
public String field = "yeliang";public static void main(String[] args) { JniTest jniTest = new JniTest(); try{ jniTest.exception(); }catch(Exception e){ System.out.println("发生异常:"+e.getMessage()); } jniTest.exception(); }
执行后报错
Exception in thread "main" java.lang.NoSuchFieldError: aa
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_exception(JNIEnv *env, jobject jobj){ jclass cls = (*env)->GetObjectClass(env,jobj); jfieldID fid = (*env)->GetFieldID(env, cls, "aa", "Ljava/lang/String;"); //检测是否发生java异常 jthrowable exception = (*env)->ExceptionOccurred(env); if (exception!=NULL){ //让java代码可以继续运行 (*env)->ExceptionClear(env); //补救措施 fid = (*env)->GetFieldID(env, cls, "field", "Ljava/lang/String;"); } //获取属性的值 jstring jstr = (*env)->GetObjectField(env,jobj,fid); char *str = (*env)->GetStringUTFChars(env,jstr,NULL); //对比属性值是否合法 // ==0相等 if (_stricmp(str, "give me the ball") != 0){ //认为抛出异常,给java层处理 jclass newexcls = (*env)->FindClass(env,"java/lang/IllegalArgumentException"); (*env)->ThrowNew(env,newexcls,"key's value is invalid"); }}
打印结果
发生异常:field's value is invalidException in thread "main" java.lang.IllegalArgumentException: field's value is invalid
虽然aa的成员变量没有找到,但是并没有抛出异常。因为把异常清空了。通过找到了名字对应的field的成员变量,并对比成员变量的值,在不相等的情况下手动抛出了一个异常。
打印的结果第一个是捕获的异常,第二个是程序直接crash。因为没有捕获。
4 缓存
c代码
JNIEXPORT void JNICALL Java_com_yeliang_JniTest_cache(JNIEnv *env, jobject jobj){ jclass cls = (*env)->GetObjectClass(env,jobj); //获取ffiedID只获取一次 //局部静态变量 static jfieldID key_id = NULL; if (key_id==NULL){ key_id = (*env)->GetFieldID(env, cls, "field", "Ljava/lang/String;"); printf("========GetFieldID===========\n"); }}
java代码
public static void main(String[] args) { JniTest jniTest = new JniTest(); jniTest.cache(); }
打印结果
========GetFieldID===========
可以看出,key_id 只初始化了一次。
5 初始化成员变量
初始化全局变量 动态库家在完成之后 立刻缓存起来
c代码
jfieldID field;jmethodID random_mid;JNIEXPORT void JNICALL Java_com_yeliang_JniTest_initIds(JNIEnv *env, jclass jcls){ field = (*env)->GetFieldID(env, jcls, "field", "Ljava/lang/String;"); random_mid = (*env)->GetMethodID(env,jcls,"getRandomInt","(I)I");}
java代码
public String field = "yeliang";public int getRandomInt(int range){ System.out.println("Java中的方法执行了"); return new Random().nextInt(range); }static{ System.loadLibrary("jni_study"); initIds(); }
阅读全文
0 0
- JNI笔记 JNI引用,异常处理,初始化成员变量
- JNI 学习笔记(三)-- JNI访问数组、引用、异常处理、缓存策略
- NDK开发学习笔记(3):JNI访问数组、引用、异常处理、缓存策略
- JNI异常的处理
- JNI异常的处理
- JNI异常的处理
- jni的异常处理
- JNI异常处理
- JNI异常处理
- JNI异常处理
- JNI异常处理
- JNI异常处理
- NDK/JNI异常处理
- JNI异常处理
- JNI异常处理
- jni字符串乱码,异常,引用....
- 成员变量指针未初始化,异常处理对象析构
- Android JNI抛出异常处理
- 获取某段时间内的小时、日期、月份,存储过程中使用的较多。
- 图像分割—基于图像数据的自动选择阈值(基本全局阈值处理方法)
- #spring注入为空null,普通类中引用springIOC类
- Navicat 导入数据报错 --- 1153
- 安装Ubuntu 出现 SQUASFS error / sd 8:0:0:0 :[sdb] assuming drive cache:write through
- JNI笔记 JNI引用,异常处理,初始化成员变量
- MySql避免重复插入记录方法(ignore,Replace,ON DUPLICATE KEY UPDATE)
- PHP求非重复字符串的最大值
- TensorFlow 介绍 tf.nn.softmax_cross_entropy_with_logits 的用法
- Struts框架中OGNL标签与EL标签表达式使用
- android 将简单的数据存储到本地-SharedPreferences
- iOS 递归下载图片更新列表
- Android视频直播的实现
- 百度地图给多个marker添加右键菜单(删除、更新)