Jni简单记录

14 篇文章 0 订阅
2 篇文章 0 订阅

LocalRef与GlobalRef

前者类似局部变量(类似,但是又有本质区别),后者类似全局变量
前者在 一次jni调用结束后,由jvm自动释放
后者需要 手动释放


LocalRef内存泄露

LocalRef与局部变量不同,它是保存在一张表中的,这张表在调用jni开始创建,一次jni调用结束后销毁
注意: LocalRef的生命周期不是一个函数,而是一次jni调用,这一点与局部变量不同
另外,如果表满,那么会出现OOM
所以,比较好的做法是,如果不用,就调用DeleteLocalRef来将这个ref从表中删除,不要等着自动释放


ReleaseStringChars

声明这个字符串指针不再使用,可以当做是delete来看
处理的是unicode类型


加速技巧

  1. 缓存常用的ref(视情况,如果涉及到包名之类的,为兼容考虑不缓存)
  2. 数组操作时,使用相应的有region的方法,对需要处理的部分数组做处理,而不是全部,因为每次处理都会有对应数量的副本产生,会耗时
  3. 一次处理数组操作,而不是分多次多数组的多个区域做操作,因为每次操作都会耗时
  4. 尽可能用参数而不是封装的对象做参数,因为获取封装对象的field需要耗时,而直接给参数会快很多
  5. 尽可能少的java和native之间的互调,可以简单认为:java层尽可能少的调用native函数,争取一次做完动作;相应的,native层尽可能少的调用jni相关的函数
  6. 设计良好的数据结构,使之符合上一条的技巧
  7. 在不需要时,调用DeleteLocalRef来删除本地引用
  8. EnsureLocalCapacity() 方法来通知 JVM 您将使用超过 16 个本地引用,不到万不得已,请勿尝试


防错技巧

  1. jni的env的跨线程处理,如果要跨线程使用,记得先缓存起来
  2. 检查异常,不是检查是否为null,而是直接对异常做处理 if((*env)->ExceptionOccurred(env)) { return; }
  3. 检查返回值,即:检查是否为null
  4. 在使用GetXXX获取数组时,不同的JVM处理是不同的,有的返回副本,有的直接返回,如果返回副本的,需要调用ReleaseXXX,并使用mode:JNI_COMMIT(0)来复制副本到实际数据并释放,否则,实际数据可能不会有任何改变,因为你一直在对副本做操作
  5. 确保代码不会在 GetXXXCritical() 和 ReleaseXXXCritical() 调用之间发起任何 JNI 调用或由于任何原因出现阻塞------原因暂时不明
  6. 记得删除GlobleRef,否则会有内存泄露

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值