JNI 筆記

  • C/C++中寫的程序可以避開JVM的內(nèi)存開銷過大的相知、處理高性能的計算、調(diào)用系統(tǒng)服務(wù)等,但是java調(diào)用jni空方法和java調(diào)用java方法相比,性能非常低的。所以一般只用來處理一些對運算有要求,或者需要對接口隱蔽的功能。

  • JNI 一般編寫流程 其實就是為了避免一些錯誤 用javah生成jni函數(shù)名,還是值得推薦使用的。驗證過,可以生成。比較使用的小技巧。

image.png

javac src/com/example/com/enjoy/test/test.java -d ./bin
javah -jni -classpath ./bin -d ./jni com.example.com.enjoy.test.test

image.png
  • apk crash 有l(wèi)og 可以定位,程序的anr 會在記錄在/data/anr/traces.txt mtk aee log也有。
    但是NDK Crash 定位就很難了 ,容易出錯的地方有 內(nèi)存地址訪問錯誤 使用野指針  內(nèi)存泄露  堆棧溢出  初始化錯誤  類型轉(zhuǎn)換錯誤 數(shù)字除0(11/0) 等等

使用ndk-stack 進(jìn)行定位到行。


image.png
  • 因為 Java 默認(rèn)使用 Unicode 編碼,而 C/C++默認(rèn)使用 UTF 編碼,所以在本地代碼中操作字符串的時候,必須使用合適的 JNI 函數(shù)把 jstring 轉(zhuǎn)換成 C 風(fēng)格的字符串。 JNI 支持字符串在 Unicode和 UTF-8 兩種編碼之間轉(zhuǎn)換,GetStringUTFChars 可以把一個 jstring 指針(指向 JVM 內(nèi)部的 Unicode字符序列)轉(zhuǎn)換成一個 UTF-8 格式的 C 字符串。
    -調(diào)用完 GetStringUTFChars 之后不要忘記安全檢查,因為 JVM 需要為新誕生的字符串分配內(nèi)存空間,當(dāng)內(nèi)存空間不夠分配的時候,會導(dǎo)致調(diào)用失敗,失敗后 GetStringUTFChars 會返回 NULL,并拋出一個 OutOfMemoryError 異常。JNI 的異常和 Java 中的異常處理流程是不一樣的,Java 遇到異常如果沒有捕獲,程序會立即停止運行。而 JNI 遇到未決的異常不會改變程序的運行流程,也就是程序會繼續(xù)往下走
  • 接口找不到
    在Java中調(diào)用JNI接口時,出現(xiàn)異常,察看日志,發(fā)現(xiàn)有如下錯誤:
    WARN/dalvikvm(422): No implementation found for native Lcom/whty/wcity/HelixPlayer;.setDllPath (Ljava/lang/String;)V
    檢查了幾遍代碼,Cpp中確實定義了這個接口,而且仔細(xì)對照了Java的包名、類名,確實沒有錯誤,那為什么會出現(xiàn)這種問題呢。后來突然想到,JNI接口 都是以C的方式定義的,現(xiàn)在使用C++實現(xiàn),函數(shù)定義前是否需要加上extern "C"呢?為此定義了一個頭文件,在CPP文件中include該頭文件,頭文件加上如下代碼片斷:

ifdef __cplusplus

extern "C" {

endif

endif

...

ifdef __cplusplus

}
再次嘗試,調(diào)用成功!

  • MTK flash tool 刷機(jī)問題 ubuntu 下刷機(jī) 出現(xiàn)了異常。
    BROM ERROR : STATUS_ERR (-1073676287)
    STATUS_BROM_CMD_SEND_DA_FAIL
    chip mismatch MT0000

這幾個問題  直接用ok機(jī)器的
/etc/udev/rules.d/  目錄下文件全部替換即可

jni讀寫文件 open 時候出錯 fd 返回-1 文件節(jié)點權(quán)限是666
剛開始以為是權(quán)限問題,chmod 666后發(fā)現(xiàn)還是不行使用java 文件流進(jìn)行讀寫 發(fā)現(xiàn)讀是ok的
寫時候出現(xiàn)異常 后面公司大神改了下驅(qū)動  將模塊驅(qū)動中映射的open函數(shù)直接返回0
還是不行 。
最后自己懷疑是selinux 問題

image.png

我的avc 異常:
[ 138.125449] <6>.(6)[283:logd.auditd]type=1400 audit(1496479197.368:93): avc: denied { read write } for pid=3144 comm="m.enjoy.testjni" name="ttctl" dev="tmpfs" ino=11250 scontext=u:r:system_app:s0 tcontext=u:object_r:ttctl_device:s0 tclass=chr_file permissive=0
修改: 
/alps/device/mediatek/common/sepolicy/system_app.te
+allow system_app ttctl_device:chr_file { read write ioctl open };
還沒驗證  下周再驗證吧。編譯實在是太慢了。
周一了周六遺留的問題解決了看log很重要,但是ioctl 返回值-1剩下就要看驅(qū)動了。

-在framework PowerManger中添加 接口,update-api 發(fā)現(xiàn)mmm但編譯之后 一直報方法未重寫,但實際已經(jīng)重寫,不明原因,直接根目錄下全編一次就好了。

  • 報checkJni錯誤一般在jni映射函數(shù)中出錯了,比如返回類型沒寫對
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容