在 Android 的 ART(Android Runtime)环境中,JNI(Java Native Interface)提供了两种注册方式:
静态注册是 JNI 方法的 默认注册方式,它通过 方法名匹配机制 来自动完成 Java 方法与本地(Native)方法的关联,不需要额外的 JNI_OnLoad
进行手动绑定。
RegisterNatives
进行注册。Java_包名_类名_方法名(JNIEnv* env, jobject obj, 参数)
在 Java 代码中,使用 native
关键字声明本地方法:
package com.example;
public class NativeTest {
static {
System.loadLibrary("native-lib"); // 加载 SO 文件
}
public native void nativeMethod(); // 声明 native 方法
}
System.loadLibrary("native-lib")
加载 SO(共享库)。nativeMethod()
只是声明,具体实现由 C/C++ 代码提供。在 C/C++ 代码中,按照 JNI 规范的命名规则 实现 nativeMethod
:
#include
#include
extern "C"
JNIEXPORT void JNICALL Java_com_example_NativeTest_nativeMethod(JNIEnv* env, jobject obj) {
printf("Native method called!\n");
}
Java_
com_example_
NativeTest
nativeMethod
此方法的 完整 JNI 方法签名:
Java_com_example_NativeTest_nativeMethod(JNIEnv* env, jobject obj)
注意:
JNIEXPORT
和 JNICALL
是 JNI 关键字,保证方法正确导出。JNIEnv* env
是 JNI 的环境变量,用于操作 Java 层对象。jobject obj
代表 Java 端调用此方法的对象实例。在 ART 虚拟机加载 Java 类时,会执行如下流程:
NativeTest
类,并检测是否包含 native 方法。FindNativeMethod()
,查找 Java_com_example_NativeTest_nativeMethod
是否在本地库 native-lib.so
中。Dlsym()
查找符号表,确认是否存在该方法:dlsym(handle, "Java_com_example_NativeTest_nativeMethod");
NativeTest.nativeMethod()
上。静态注册的流程按照以下顺序进行:
dlopen("libnative-lib.so")
dlsym()
查找 JNI_OnLoad
(如果有)JNI_OnLoad
,则进入 静态注册流程。NativeTest
类
nativeMethod()
,需要进行 JNI 绑定。dlsym()
在 libnative-lib.so
中查找 Java_com_example_NativeTest_nativeMethod
。Java_com_example_NativeTest_nativeMethod()
绑定到 NativeTest.nativeMethod()
。nativeMethod()
时,ART 直接执行 Java_com_example_NativeTest_nativeMethod()
。对比项 | 静态注册 | 动态注册 |
---|---|---|
方法命名 | 必须符合 Java_包名_类名_方法名 |
可以任意命名 |
注册方式 | ART 自动解析 | 需要手动调用 RegisterNatives() |
JNI_OnLoad | 可选 | 必须实现 |
性能 | 较快,直接查找符号表 | 稍慢,需要额外解析 |
适用场景 | 简单方法,不涉及复杂映射 | 混淆代码 或 多版本兼容 |
✅ 适用于 方法数量较少、名称稳定 的 JNI 方法。
✅ 适用于 无需混淆的 Native 方法,因为方法名必须遵循 Java_xxx
规则。
✅ 适用于 性能要求较高的应用,静态注册比动态注册略快。
RegisterNatives()
,ART 通过 dlsym() 自动解析 JNI 方法。JNI_OnLoad
的额外开销。Java_xxx_xxx_xxx
规则,无法进行灵活的命名。