1. 程式人生 > >解決JNI呼叫在Android5.0+閃退問題

解決JNI呼叫在Android5.0+閃退問題

日誌資訊如下:
08-14 15:48:41.127: A/art(5526): art/runtime/check_jni.cc:70] JNI DETECTED ERROR IN APPLICATION: illegal class name ‘xxx.xxx.xxx’
08-14 15:48:41.127: A/art(5526): art/runtime/check_jni.cc:70] (should be of the form ‘package/Class’, [Lpackage/Class;’ or ‘[[B’)
08-14 15:48:41.127: A/art(5526): art/runtime/check_jni.cc:70] in call to FindClass

看日誌是在呼叫FindClass時出錯了。在FindClass的時候會呼叫CheckClassName方法檢查類名是否合法。CheckClasName方法原始碼如下:

  // Checks that 'class_name' is a valid "fully-qualified" JNI class name, like "java/lang/Thread"
  // or "[Ljava/lang/Object;". A ClassLoader can actually normalize class names a couple of
  // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some
// circumstances, but this is incorrect. void CheckClassName(const char* class_name) { if (!IsValidJniClassName(class_name)) { JniAbortF(function_name_, "illegal class name '%s'\n" " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", class_name); } }



在CheckClassName方法中呼叫了IsValidJniClassName方法,通過google搜尋”IsValidJniClassName site:android.googlesource.com”,發現IsValidJniClassName方法的宣告在utils.h中,實現在utils.cc中。
這裡寫圖片描述

IsValidJniClassName方法實現如下:
這裡寫圖片描述
他呼叫了IsValidClassName方法,注意第三個引數是'/',這是類名的分隔符,而我這裡呼叫FindClass時類名是使用了'.'分隔,改成'/',問題就解決了。

Android5.0之後jni相關的兩個修改:
1.JNI呼叫規則
統一類名以”/”分隔,而不相容”.”。比如:com.linchaolong.Test要改成com/linchaolong/Test
2.動態庫的搜尋規則
so搜尋路徑統一了,比如,a.so在armeabi目錄下找到了,則接下來的so都會在armeabi目錄下面搜尋,沒有則可能出現閃退。