JNI调用注意事项

所谓jni,就是java和c互相调用的方式。由于C语言调用java的比较少,所以,本文所指的就是用java调用C语言写的动态库的方式。
用java调用C语言的动态库,可以在效率和安全性上获得一定的效果;但是由于C语言可以直接访问内存空间,如果在编码上不严谨,极容易出现小错误从而影响jdk/jre的正常运行。目前所见有以下几个问题:
1. 内存泄漏;容易导致jdk/jre在运行期占用大量的内存,内存消耗会随着应用运行的时间逐步增加。
2. 数组越界;会导致不可想象的后果,包括运算结果错误和jre dump。
3. 读写空指针;直接就会导致jre dump。
4. 接口不匹配;在hotspot上表现为jre dump,并且没有任何有意义的提示信息。
综上,可知jni是一种风险较高的编程方式,如果不是从安全和效率的角度考虑,应尽量避免使用。
对于必须要使用jni的应用,应反复审查C部分的代码,注意以下几个方面:
1. 安排专人负责jni尤其是动态库部分的编码,并安排经验丰富的人员进行代码检查。
2. 注意保证java部分和C部分的接口保持一致,避免误提示信息的jre dump。
3. 在C程序中对java传入的参数的进行严格检查,尤其是数组参数和字符串参数,要注意数据的长度和合法性。
4. 在C程序中要注意字符串和字符数组的区别。对于java中String类的参数,在C语言中表现为字符串,以0x00为结束符,可以使用str*类函数操作,譬如strcpy等;特别要注意用Get*String*类jdk提供的函数处理时可能是与语言编码息息相关的,譬如对于中文字符串GetStringLength得到的长度与strlen是不一样的。而对于java中的byte[]类参数,在C语言中表现为字符数组,无结束符,需要自行获取数据长度,可以用mem*类函数操作,譬如memcpy;要注意这类参数不能通过strlen得到准确长度,应自行传递数据长度或使用Get*ArrayLength类函数取得数据长度。
5. 要避免隐式的内存泄露,在C语言中注意如果有申请内存一定要释放,即*alloc和free要成对出现;而从java传递的参数中获取信息后也要及时释放引用,即Get*和Release*类函数要成对使用,譬如在调用GetByteArrayElements后,应调用ReleaseByteArrayElements通知jre释放对这部分内存的引用。
6. 要避免在C语言中出现读写空指针的情况,在对指针进行读写前应判断其可用性,C动态库的dump会导致jre的dump,由于jre中不存在process的概念,这会使得整个jre退出。
7. 防止数组读写越界,在C语言中出现读写越界时,可能会导致动态库dump,从而使得jre退出;但在某些系统/编译器下,可能会出现把数据写到静态变量(static)区的情况,这时,不会出现dump的情况,但由于静态变量被修改,任何引用了静态变量的计算都会得到错误的结果;所以,请尽量少用静态变量,如有使用,请注意保证变量的值不会被无意篡改。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值