jni编写时的教训(函数签名不对应)

最近由于项目结构上的调整

原先我的模块位于APP层,通过aidl,hidl调用到native层的c++的服务的接口,用于更新EMMC上的文件内容,需要改为

C++服务更新EMMC上文件内容的代码封装成jni的so库,由我的模块去调用。

由于jni仓库是由我去创建,因此,我需要创建jni仓库,增加Android.mk,同时添加cpp文件,完成jni的so中的接口函数的空实现以及native方法的注册,问题就处在方法的注册上面,给我很大的教训,由于一个很小的疏忽。

我有个本地方法,需要返回字符串,因此,我在使用registerNativeMethod方法注册时,传入的本地方法数组中,该方法的签名是这样的:

()Ljava/lang/String

然后,在实际java进程跑到loadLibrary加载jni的so时,会调用到on_Load中的registerNativeMethod方法,报错了,墓碑显示挂在/art/runtime/jni_internal.cc中的registerNative函数,查看registerNative中的代码,发现其返回JNI_ERROR的错误,很有可能是由于签名对不上,即art虚拟机拿着jni中给他的函数签名,去实际的java的class找其对应申明的native函数找不到,于是就报错了。

按照这个方向,重新阅读了一下jni的使用方法,重点看了jni和java的类型对应转换,发现一个很重要的问题,除了基本类型和数组类型,其他的对象类型,都是以;结尾的,;并不是一个结束符或者分割符。

于是,修改了注册的本地方法表中的函数签名后,问题解决,同时发现,函数签名是可以通过javap -s命令从class文件中提取出来的,art就是使用这种方式从class中提取函数签名用于和注册的方法表中的函数签名进行匹配的。

 

看来还是太粗心了,仔细阅读对应的文档还是相当重要的,不要在自以为差不多的情况下就动手开撸,事倍功半。

你可能感兴趣的:(java,android)