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中提取函數簽名用於和註冊的方法表中的函數簽名進行匹配的。

 

看來還是太粗心了,仔細閱讀對應的文檔還是相當重要的,不要在自以爲差不多的情況下就動手開擼,事倍功半。

發佈了87 篇原創文章 · 獲贊 16 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章