1. Java 代码 (DynamicJNIDemo.java)
public class DynamicRegisterDemo {
static {
System.loadLibrary("dynamicregister"); // 加载动态库 dynamicregister.dll
}
// 声明 native 方法
public native void sayHello();
public static void main(String[] args) {
new DynamicRegisterDemo().sayHello();
}
}
2. C++ 实现 (DynamicJNIDemo.cpp)
#include <jni.h>
#include <iostream>
// 本地方法实现
void nativeSayHello(JNIEnv* env, jobject obj) {
std::cout << "Hello from dynamically registered JNI method!" << std::endl;
}
// 定义方法表(关键:方法签名必须与 Java 方法严格匹配)
static JNINativeMethod methods[] = {
{"sayHello", "()V", (void*)&nativeSayHello} // 方法名、签名、函数指针
};
// JNI_OnLoad 入口函数(动态注册的核心)
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = nullptr;
jint result = vm->GetEnv((void**)&env, JNI_VERSION_21);
if (result != JNI_OK) {
return JNI_ERR;
}
// 获取 Java 类对象
jclass clazz = env->FindClass("DynamicRegisterDemo");
if (clazz == nullptr) {
return JNI_ERR;
}
// 注册本地方法
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]) < 0)) {
return JNI_ERR;
}
return JNI_VERSION_21
;
}
2. 编译动态库(Windows)
使用 MinGW:
g++ -I $JAVA_HOME/include -I $JAVA_HOME/include/win32 -shared -o dynamicregister.dll DynamicRegisterDemo.cpp
3. 运行程序
java -Djava.library.path=. DynamicRegisterDemo
动态注册的核心优势
| 特性 | 说明 |
|---|---|
| 函数名自由 | 无需遵循 Java_ClassName_MethodName 的严格命名规则。 |
| 延迟绑定 | 可在运行时动态注册或替换方法实现。 |
| 减少头文件依赖 | 无需通过 javac -h 生成头文件,直接通过方法表绑定。 |
| 代码更简洁 | 集中管理所有 JNI 方法,适合大型项目。 |
常见问题解决
1. UnsatisfiedLinkError 错误
-
原因:动态库未找到或注册失败。
-
解决:
- 确保动态库名称与
System.loadLibrary("dynamicregister")中的名称一致(Windows 要求库名为dynamicregister.dll)。 - 检查
java.library.path是否包含动态库所在目录。
- 确保动态库名称与
2. RegisterNatives 注册失败
-
原因:方法签名错误或类名不匹配。
-
解决:
- 使用
javap -s确保方法签名严格一致。 - 检查类名全路径(如果类在包中,需使用
com/example/DynamicRegisterDemo格式)。
- 使用
3. JNI 版本冲突
- 原因:未在
JNI_OnLoad中返回正确的 JNI 版本。 - 解决:确保返回
JNI_VERSION_1_8或更高版本(JDK21 兼容 1.8)。