You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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[]);
}

核心原因

  1. ProGuard规则匹配错误:当前规则仅保留TestTool子类的目标方法,但nativeCompleteCallback是TestTool自身的私有方法,规则未覆盖到。
  2. AOSP编译优化更激进:AOSP的R8/ProGuard优化策略比Android Studio默认配置更严格,未被保留的私有方法会被直接移除(即使未混淆)。
  3. 类初始化阶段的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 02:45:35