最近在使用 jni 的时候遇到一个错误,各种百度也没有结果,最终还是定下心来仔细阅读了报错 log,做了对比实验才解决。
报错log:
2020-04-28 11:28:29.814 10214-10214/com.xxxx.test A/art: art/runtime/java_vm_ext.cc:470] JNI DETECTED ERROR IN APPLICATION: jstring has wrong type: java.lang.Class<com.xxxx.test.MainActivity>
2020-04-28 11:28:29.814 10214-10214/com.xxxx.test A/art: art/runtime/java_vm_ext.cc:470] in call to GetStringLength
2020-04-28 11:28:29.814 10214-10214/com.xxxx.test A/art: art/runtime/java_vm_ext.cc:470] from void com.xxxx.test.MainActivity.native_setSocketFileName(java.lang.String)
报错代码:
static void set_socket_name_native(JNIEnv *env, jstring file_path) {
int len = env->GetStringLength(file_path);
char buff[len + 1];
env->GetStringUTFRegion(file_path, 0, len, buff);
buff[len] = '\0';
ALOGD("%s, file path: %s", __FUNCTION__, buff);
set_socket_name(buff);
}
报错的关键是这句话 jstring has wrong type: java.lang.Class<com.xxxx.test.MainActivity> in call to GetStringLength
。
初始不明白这句话的意思,以为是字符串中包含特殊字符导致,但是通过 static 注册的 jni 函数执行相同的代码没有问题。
再次仔细理解报错关键,可以发现,报错的关键点在于 jstring has wrong type: java.lang.Class<com.xxxx.test.MainActivity>
,而我们的在使用静态注册的时候是有传入一个 jclass 参数的,虽然没有用到。
修改了代码之后发现,确实传入了 jclass 参数之后就可以正常运行。虽然 jclass 这个参数咱们写的代码没有用到,但是动态注册的时候其实是有使用到的,如果使用到 jni 相关的函数,务必传入 jclass 参数。
修正代码:
- static void set_socket_name_native(JNIEnv *env, jstring file_path) {
+ static void set_socket_name_native(JNIEnv *env, jclass obj, jstring file_path) {
int len = env->GetStringLength(file_path);
char buff[len + 1];
env->GetStringUTFRegion(file_path, 0, len, buff);
buff[len] = '\0';
ALOGD("%s, file path: %s", __FUNCTION__, buff);
set_socket_name(buff);
}