Android NDK集成AddressSanitizer时JNI转换jstring至char*崩溃求助
问题描述
尝试在JNI代码中集成内存检测工具AddressSanitizer时触发崩溃,仅调用基础JNI函数将jstring转为char*就出现问题。
JNI代码
JNIEXPORT void JNICALL Java_com_example_test_HelloJni_test2(JNIEnv *env, jclass clazz, jstring app_id) { const char *c_app_id = (*env)->GetStringUTFChars(env, app_id, NULL); (*env)->ReleaseStringUTFChars(env, app_id, c_app_id); }
崩溃日志
09:29:09.742 I AddressSanitizer can not provide additional info. 09:29:09.743 I SUMMARY: AddressSanitizer: SEGV (/data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!/lib/arm64-v8a/libhellojni.so+0xa78) 09:29:09.743 I ==19624==ABORTING 09:29:09.743 A Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 19624 (xample.asantest), pid 19624 (xample.asantest) 09:29:09.793 A pid: 19624, tid: 19624, name: xample.asantest >>> com.example.asantest <<< 09:29:09.793 A Abort message: '================================================================= ==19624==ERROR: AddressSanitizer: SEGV on unknown address 0x1680001f704e12fe (pc 0x007a54e7ca7c bp 0x007ff16a2550 sp 0x007ff16a24f0 T0) ==19624==The signal is caused by a READ memory access. #0 0x7a54e7ca78 (/data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!/lib/arm64-v8a/libhellojni.so+0xa78) #1 0x7ac2005ed4 (/apex/com.android.art/lib64/libart.so+0x13ced4) #2 0x7ac1ffc7e8 (/apex/com.android.art/lib64/libart.so+0x1337e8) #3 0x7ac2071a94 (/apex/com.android.art/lib64/libart.so+0x1a8a94) #4 0x7ac21e1460 (/apex/com.android.art/lib64/libart.so+0x318460) #5 0x7ac21d778c (/apex/com.android.art/lib64/libart.so+0x30e78c) #6 0x7ac2548a88 (/apex/com.android.art/lib64/libart.so+0x67fa88) #7 0x7ac1ff6994 (/apex/com.android.art/lib64/libart.so+0x12d994) #8 0x7ac21ced88 (/apex/com.android.art/lib64/libart.so+0x305d88) #9 0x7ac2534838 (/apex/com.android.art/lib64/libart.so+0x66b838) #10 0x7ac2005ff8 (/apex/com.android.art/lib64/libart.so+0x13cff8) #11 0x7ac1ffc564 (/apex/com.android.art/lib64/libart.so+0x133564) #12 0x7ac2071a78 (/apex/com.android.art/lib64/libart.so+0x1a8a78) #13 0x7ac241ecb8 (/apex/com.android.art/lib64/libart.so+0x555cb8) #14 0x7ac239e39c (/apex/com.android.art/lib64/libart.so+0x4d539c) #15 0x7028c6f4 (/apex/com.android.art/javalib/arm64/boot.oat+0x8a6f4) AddressSanitizer can not provide additional info. SUMMARY: AddressSanitizer: SEGV (/data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!/lib/arm64-v8a/libhellojni.so+0xa78) ' 09:29:09.963 A #01 pc 000000000004d60c /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libclang_rt.asan-aarch64-android.so (offset 0x1a000) (BuildId: 1faa253e88d6ebbf067a087f1b98301177b89a56) 09:29:09.963 A #02 pc 000000000004c5d8 /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libclang_rt.asan-aarch64-android.so (offset 0x1a000) (BuildId: 1faa253e88d6ebbf067a087f1b98301177b89a56) 09:29:09.963 A #03 pc 00000000000a3300 /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libclang_rt.asan-aarch64-android.so (offset 0x1a000) (BuildId: 1faa253e88d6ebbf067a087f1b98301177b89a56) 09:29:09.963 A #04 pc 00000000000a2f84 /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libclang_rt.asan-aarch64-android.so (offset 0x1a000) (BuildId: 1faa253e88d6ebbf067a087f1b98301177b89a56) 09:29:09.963 A #05 pc 00000000000a2944 /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libclang_rt.asan-aarch64-android.so (offset 0x1a000) (BuildId: 1faa253e88d6ebbf067a087f1b98301177b89a56) 09:29:09.963 A #07 pc 0000000000000a78 /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!libhellojni.so (offset 0x1000) (Java_com_example_test_HelloJni_test2+40) (BuildId: 7599dcbc83b75ee9ec6d54f3d0f3af9705e6ba1d) 09:29:09.964 A #15 pc 000000000001f230 [anon:dalvik-classes2.dex extracted in memory from /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk!classes2.dex] (com.example.asantest.MainActivity.onBtnUseAfterFreeClick+4) 09:29:09.964 A #30 pc 000000000008e0ea [anon:dalvik-classes.dex extracted in memory from /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk] (androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick+50) 09:29:09.964 A #36 pc 000000000018c712 [anon:dalvik-classes.dex extracted in memory from /data/app/~~CvebpWoNaOlgcXHnC8RQpw==/com.example.asantest-uYPhnYp__1cAO8Eu5NNL8A==/base.apk] (com.google.android.material.button.MaterialButton.performClick+6) ---------------------------- PROCESS ENDED (19624) for package com.example.asantest ----------------------------
问题排查与解决
核心原因
崩溃发生在GetStringUTFChars调用阶段,最可能的触发点是:
- Java层传入了null的jstring参数,JNI直接对空指针调用JNI函数触发段错误;
- AddressSanitizer编译链接配置不完整,导致工具本身兼容性问题;
- JNI方法签名与Java层声明不匹配,参数传递异常。
修复步骤
1. 添加参数非空校验
在JNI函数开头增加null判断,避免对空指针操作:
JNIEXPORT void JNICALL Java_com_example_test_HelloJni_test2(JNIEnv *env, jclass clazz, jstring app_id) { if (app_id == NULL) { // 抛出Java空指针异常提示调用方 jclass exceptionClz = (*env)->FindClass(env, "java/lang/NullPointerException"); (*env)->ThrowNew(env, exceptionClz, "app_id cannot be null"); return; } const char *c_app_id = (*env)->GetStringUTFChars(env, app_id, NULL); if (c_app_id != NULL) { (*env)->ReleaseStringUTFChars(env, app_id, c_app_id); } }
同时确保Java层调用native方法时传入的字符串不为null。
2. 检查ASAN编译配置
确保CMake/Android.mk中正确配置ASAN参数:
- CMake配置示例:
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address") - 要求minSdkVersion ≥26(Android 8.0+),低版本系统对ASAN支持有限。
3. 验证JNI方法签名
确认Java层native方法声明与JNI函数完全匹配:
Java层代码应为:
public static native void test2(String app_id);
包名、类名、方法名、参数类型必须严格对应,签名不匹配会导致参数传递错乱。
验证
修复后重新编译安装应用,触发JNI调用,确认崩溃不再发生。若仍有问题,可暂时关闭ASAN排查是否为工具兼容性问题,再逐步定位。
内容的提问来源于stack exchange,提问作者Sucer Li
相关产品推荐
相关产品推荐

