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

JNI全原生实现:如何移除指定文件剩余Java层override方法声明

解决方案

完全可以实现将对应Java文件的所有逻辑迁移到原生层,不需要在源码层面保留override方法的native声明,可通过以下两种方案实现:

方案1:编译期字节码插桩

  • 原理:编译阶段通过ASM、Javassist等字节码操作工具,自动向目标类插入你需要的native方法声明,你本地开发的Java源码可以完全清空所有逻辑,仅保留空类定义即可,打包后字节码里会自动生成对应的native声明供JNI注册使用。
  • 注意事项:
    • 插桩逻辑要在混淆前执行,同时给自动生成的native方法添加混淆排除规则,避免被ProGuard/R8优化移除
    • 插桩逻辑本身可以加密放到构建脚本里,避免逆向人员拿到插桩规则反向还原方法列表

方案2:运行时动态生成类

  • 原理:完全不需要提前编写Java类,在JNI_OnLoad执行阶段,通过JNI调用Android系统的DexClassLoader,或者在原生层直接拼接dex字节码,动态生成继承自目标父类(比如Activity)的子类,自动重写所有需要override的方法,直接给动态生成的类注册原生方法实现,最后替换AndroidManifest中注册的启动类为动态生成的类即可,源码层面完全没有相关Java代码。
  • 注意事项:
    • Android 11及以上版本对动态加载的dex、动态生成的字节码有更严格的校验,需要提前适配隐藏API绕过逻辑,避免方法调用被拦截
    • 部分定制ROM对动态类的加载有限制,需要提前做好兼容性测试

现有代码优化建议

你当前的实现可以做以下调整提升防篡改效果:

  1. 原生层onCreate方法里创建的全局引用,要在Activity的onDestroy回调里调用DeleteGlobalRef释放,避免内存泄漏
  2. 注册完JNI方法后清空natives数组的操作可以保留,能提升内存dump时获取方法映射关系的门槛
  3. 如果选择插桩方案,可以配合dex整体加密,把残留的Java空类也放到加密dex里,启动时在原生层解密加载,进一步提升逆向难度

现有参考代码

Java层现有代码

@Override
protected native void onCreate(Bundle savedInstanceState);

CPP层现有代码

void onCreate(JNIEnv *env, jobject classObject, jobject bundle) {
    /**super.onCreate**/
    gObjects[0] = env->NewGlobalRef(classObject);
    gClasses[0] = env->GetObjectClass(gObjects[0]);
    jclass s_Class = env->GetSuperclass(gClasses[0]);
    jmethodID oc_ID = env->GetMethodID(s_Class, "onCreate", "(Landroid/os/Bundle;)V");
    env->CallNonvirtualVoidMethod(gObjects[0], gClasses[0], oc_ID, bundle);
}

extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *curVM_, void *reserved) {
    curVM = curVM_;
    curVM->GetEnv((void **) &environments[0], JNI_VERSION_1_6);

    /**Start of Native Method Registers**/
    JNINativeMethod natives[1];
    uint64_t pCount = sizeof(natives) / sizeof(natives[0]);
    jclass klass = environments[0]->FindClass("com/company/app/Activity");
    natives[0] = {"onCreate", "(Landroid/os/Bundle;)V", (void *)onCreate};
    environments[0]->RegisterNatives(klass , natives, pCount);
    for (uint64_t i = 0; i < pCount; i++) natives[i] = {"", ""};

    return JNI_VERSION_1_6;
}

内容的提问来源于stack exchange,提问作者user11988193

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 11:27:04