AOSP中JNI调用getMethodID触发NoSuchMethodError问题求助
AOSP迁移后JNI调用NoSuchMethodError问题解决
问题现象
在Android Studio中使用Android.mk+ndk-build构建APK运行正常,迁移至AOSP编译成功后,运行时抛出错误:
AndroidRuntime: java.lang.NoSuchMethodError: no non-static method
"Lcom/example/TestTool;.nativeCompleteCallback([B)V"
相关配置与代码
Android.bp
cc_library_shared { name: "TestLib", srcs: [ "jni/*.cc", ], arch: { arm: { instruction_set: "arm", }, }, } android_app { name: "Test_APP", srcs: [ "src/**/*.java", ], product_specific: false, platform_apis: true, certificate: "platform", resource_dirs: ["src/main/res"], asset_dirs: ["src/main/assets"], required: ["TestLib"], jni_libs: ["TestLib"], static_libs: [], optimize: { proguard_flags_files: ["proguard.cfg"], }, }
Java代码(TestTool.java)
public class TestTool { private final static String LOG_TAG = "TestTool"; static { Log.d(LOG_TAG, "loadLibrary"); System.loadLibrary("TestLib"); nativeClassInit(); } ... private void nativeCompleteCallback(byte[] testData) { Log.d(LOG_TAG, "native Complete Callback"); ... } ... private static native final boolean nativeClassInit(); }
JNI代码
JNIEXPORT jboolean JNICALL Java_com_example_TestTool_nativeClassInit(JNIEnv * env, jclass cls) { METHOD_nativeSynthCallback = env->GetMethodID(cls, "nativeCompleteCallback","([B)V"); return JNI_TRUE; }
已尝试的无效ProGuard规则
-keepclassmembers class * extends com.example.TestTool { private void nativeCompleteCallback(byte[]); }
核心原因
- ProGuard规则匹配错误:当前规则仅保留
TestTool子类的目标方法,但nativeCompleteCallback是TestTool自身的私有方法,规则未覆盖到。 - AOSP编译优化更激进:AOSP的R8/ProGuard优化策略比Android Studio默认配置更严格,未被保留的私有方法会被直接移除(即使未混淆)。
- 类初始化阶段的JNI查找:静态代码块中调用
nativeClassInit时,类初始化阶段尝试获取实例方法ID,若方法已被优化移除则会抛出错误。
解决方案
1. 修正ProGuard规则
直接保留TestTool类的目标方法,替换原有规则:
-keepclassmembers class com.example.TestTool { private void nativeCompleteCallback(byte[]); }
若需彻底避免类方法被优化,可直接保留整个类:
-keep class com.example.TestTool { *; }
2. 验证方法签名正确性
使用javap工具生成类的方法签名,确认与JNI中使用的一致:
javap -s -p com.example.TestTool
输出中找到nativeCompleteCallback的签名,确保为([B)V(参数为byte数组,返回值void)。
3. 排查AOSP编译优化配置
临时关闭优化验证问题:
在Android.bp的android_app块中修改:
optimize: { enabled: false, // proguard_flags_files: ["proguard.cfg"], },
若关闭后运行正常,说明问题源于优化规则,重新开启后调整ProGuard规则即可。
4. 确认APK中方法存在性
解压APK检查classes.dex中是否包含目标方法:
unzip -p Test_APP.apk classes.dex | dexdump -d | grep "nativeCompleteCallback"
若未找到该方法,说明编译时方法被移除,需重新检查ProGuard和编译配置。
内容的提问来源于stack exchange,提问作者S Tung
相关产品推荐
相关产品推荐

