面向 Android/Gradle 的轻量 JNI Zero 生成方案。
本工程沿用 Chromium JNI Zero 的注解、C++ 调用约定和 runtime,但把 Python 生成链路 替换为 Java 17 Gradle 插件。它适合仓库内的 application/library 模块复用,目前不作为 通用 Maven 插件发布。
接入一个模块后,新增 JNI 类通常只改两个地方:
- Java 中声明
@NativeMethods/@CalledByNative。 - C++ 中实现
JNI_<Class>_<Method>。
插件负责:
- 扫描 Java AST,生成
<Class>Jni.java和 C++ headers; - 把生成的 Java 加入 AGP,把 headers 接到对应 CMake target;
- 按模块和 source set 隔离产物,不维护逐类 binding 清单;
- 用生成宏在 C++ 编译期检查缺失实现和签名错误;
- 为 Android library 提供 R8 consumer rules;
- 生成可缓存的 Gradle task,不依赖 Python 或 Chromium checkout。
如果 C++ 实现放在 target 已编译的源码中,同一个 source set 新增 JNI 类时不需要再修改 Gradle 或 CMake。
需要 JDK 17、Android SDK 36、NDK 27.0.12077973 和 CMake 3.22.1。
./gradlew :app:assembleDebugAPK 位于 app/build/outputs/apk/debug/app-debug.apk。示例覆盖双向调用、全部支持类型,
以及 application 与多个 Android library 各自加载 .so。
模块只需要配置一次。完整范例可直接参考
libraries/jni-alpha。
plugins {
id("com.android.application") // Android library 使用 com.android.library
id("dev.chromium.jni-zero")
}
dependencies {
implementation(project(":jni-zero-api"))
}
jniZero {
nativeLibrary("feature_jni")
}nativeLibrary 是实现该模块 JNI 方法的 CMake target。Android library 通常使用
compileOnly(project(":jni-zero-api")),避免多个 AAR 重复打包注解类。
模块的常规 Android/NDK 配置还需要:
- 使用 Java 17 和 C++20;
- 把
third_party/jni_zero作为JNI_ZERO_ROOT传给 CMake; - 配置
externalNativeBuild。
仓库内可复制的配置见
libraries/jni-alpha/build.gradle.kts。
package com.example.feature;
import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
@JNINamespace("feature")
public final class FeatureBridge {
static {
System.loadLibrary("feature_jni");
}
private FeatureBridge() {}
public static int add(int left, int right) {
return FeatureBridgeJni.get().add(left, right);
}
public static String greeting(String value) {
return FeatureBridgeJni.get().greet(value);
}
@CalledByNative
private static String decorate(String value) {
return "Java callback: " + value;
}
@NativeMethods
interface Natives {
int add(int left, int right);
String greet(String value);
}
}FeatureBridgeJni 不需要手写,它会在构建时生成。
#include "third_party/jni_zero/jni_zero.h"
#include "FeatureBridge_jni.h"
namespace feature {
static int32_t JNI_FeatureBridge_Add(int32_t left, int32_t right) {
return left + right;
}
static jni_zero::ScopedJavaLocalRef<jstring> JNI_FeatureBridge_Greet(
JNIEnv* env,
const jni_zero::JavaRef<jstring>& value) {
return Java_FeatureBridge_decorate(env, value);
}
} // namespace feature
DEFINE_JNI(FeatureBridge)
extern "C" __attribute__((visibility("default"))) jint JNI_OnLoad(
JavaVM* vm,
void*) {
jni_zero::InitVM(vm);
return JNI_VERSION_1_6;
}DEFINE_JNI(FeatureBridge) 会把生成的 JNI boundary 展开,并在编译期检查上面的实现。
模块需要一个 jni_zero_runtime target。业务 target 在链接 runtime 后,包含插件生成的
manifest:
add_library(feature_jni SHARED feature_bridge.cc)
target_link_libraries(feature_jni PRIVATE jni_zero_runtime)
# 必须放在相关 add_library() 之后
include("${JNI_ZERO_LIBRARIES_FILE}")runtime sources、include directory 和 Android log library 的完整配置见
app/src/main/cpp/CMakeLists.txt。
./gradlew :your-module:generateJniZero
./gradlew :your-module:assembleDebug生成文件和诊断报告位于模块的 build/generated/jniZero/ 与
build/reports/jniZero/,不需要提交。需要审阅的稳定基线放在
src/test/jniZeroGolden/。
main 默认扫描 src/main/java。一个模块需要额外 Java 目录或多个 CMake target 时,
增加 source set:
jniZero {
nativeLibrary("feature_core_jni")
sourceSet("media") {
javaSources("src/mediaJni/java")
nativeLibrary("feature_media_jni")
}
}插件只把 media 生成的 headers 提供给 feature_media_jni。更多约束和任务名称见
JNI source sets。
当前支持:
- nested
@NativeMethodsinterface; - static
@CalledByNative; @JNINamespace;- primitive、
String、Object和Object[]; - Java → C++ 与 C++ → Java;
- 多 Android module、模块内多 source set/native library。
一个类只能有一个 @NativeMethods interface,native 和 callback 方法不能重载。
instance callback、primitive array、任意业务对象转换、variant 专属 JNI 和 JAR/AAR
扫描尚不支持。错误会在生成阶段指出源码路径、行和列。
本工程选择 per-file natives,不实现 Chromium 的全程序 registration、GEN_JNI、短名
和 multiplexing。这样牺牲一部分极限体积优化,换取更简单的 Gradle/CMake 接入。
详细取舍见 设计说明。
# JVM parser/emitter
./gradlew -p build-logic :jni-zero-codegen:check
# Android 构建、C++ 签名检查和 golden
./gradlew -PjniZeroAbis=arm64-v8a :app:assembleDebug :app:check
# Release + R8
./gradlew -PjniZeroAbis=arm64-v8a :app:assembleRelease设备测试、16 KB 对齐和 CI 覆盖见 测试说明。 生成器内部维护见 Codegen,待办见 Roadmap。
本仓库自行实现的代码使用 Apache License 2.0。
third_party/jni_zero 保留 Chromium 上游版权和
BSD 许可证,同步方式见
third_party/jni_zero/README.md。