Android运行时找不到native代码实现,调用JNI方法崩溃该如何解决?
问题排查与修复方案
核心问题根因(按发生概率从高到低排序)
- JNI函数未添加
extern "C"修饰:C++编译器会对未加extern "C"的函数做名字修饰(Name Mangling),即使函数名拼写完全正确,ART运行时也无法匹配到对应的JNI符号。 - Java方法与JNI实现签名不匹配:你贴出的Java层
ReadBatch方法仅声明3个String参数,但JNI实现、自动生成的头文件、Logcat报错里的目标方法都是4个String参数,同时静态/非静态属性也存在不一致。 - 构建缓存不同步:修改代码后未清理旧构建缓存,导致打包的APK内仍为旧版本代码。
具体修复步骤
步骤1:给JNI函数添加extern "C"包裹
修改你的cpp实现代码,将JNI函数放在extern "C"块中,避免C++编译器篡改符号名,同时补上字符串资源释放逻辑避免内存泄漏:
extern "C" { JNIEXPORT jlong JNICALL Java_fr_uni_researchdemo_Wrapper_ReadBatch (JNIEnv *pEnv, jobject obj, jstring strBatchFile, jstring strInputFile, jstring strOutputFile, jstring strLogFile) { char* pBatch = (char*)pEnv->GetStringUTFChars(strBatchFile, nullptr); char* pInput = (char*)pEnv->GetStringUTFChars(strInputFile, nullptr); char* pOutput = (char*)pEnv->GetStringUTFChars(strOutputFile, nullptr); long lResult = read_batch(pBatch, pInput, pOutput); // 释放JNI字符串资源,必须添加否则会内存泄漏 pEnv->ReleaseStringUTFChars(strBatchFile, pBatch); pEnv->ReleaseStringUTFChars(strInputFile, pInput); pEnv->ReleaseStringUTFChars(strOutputFile, pOutput); return lResult; } }
步骤2:对齐Java层与JNI层方法签名
根据你的业务逻辑二选一即可:
- 如果你实际需要4个参数,将Java层方法修改为:
public native long ReadBatch(String strBatchFile, String strInputFile, String strOutputFile, String strLogFile);
- 如果你实际只需要3个参数,删除JNI实现、头文件中多余的
jstring strLogFile参数。
同时确认方法的静态属性匹配:如果Java层方法添加了static修饰,JNI函数的第二个参数需改为jclass;如果是普通实例方法,保持jobject即可。
步骤3:清理缓存重新构建
在Android Studio中依次点击 Build → Clean Project → Rebuild Project,清理旧构建缓存后重新打包安装。
步骤4:验证符号正确性
构建完成后用以下命令校验so库的导出符号:
nm -D libnativelib.so | grep ReadBatch
正常输出应为Java_fr_uni_researchdemo_Wrapper_ReadBatch,如果存在_Z等前缀说明extern "C"未生效,需重新检查cpp代码。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

