如何使用javac生成名称稳定的头文件(避免函数名含1)
解决JNI头文件函数名自动插入"1"的问题
原因分析:JNI的命名规则里,下划线
_是用来分隔包名、类名和方法名的特殊字符。当Java native方法名本身包含下划线时,javac会自动将方法名里的下划线转义为_1,避免和分隔符混淆,所以生成的头文件函数名会出现_1。解决方案1:修改Java方法名(推荐)
直接移除native方法名中的下划线,改用Java标准的驼峰命名法,示例:package examples.logging; public class FastLogging { public static native long loggingNew(int level, String domain, boolean console, String file, String server, String connect, int max_size, int backlog); public static native void loggingSetLevel(long instance_ptr, int level); // ... }重新执行
javac -h . examples/logging/FastLogging.java,生成的头文件函数名将变为Java_examples_logging_FastLogging_loggingNew和Java_examples_logging_FastLogging_loggingSetLevel,不会再出现_1。解决方案2:使用JNI动态注册(兼容原有方法名)
如果需要保留原有Java方法名的下划线,可通过JNI动态注册的方式绑定方法,无需遵循自动生成的命名规则:- 编写JNI实现函数时自定义函数名,比如:
#include <jni.h> JNIEXPORT jlong JNICALL native_logging_new(JNIEnv *env, jclass clazz, jint level, jstring domain, jboolean console, jstring file, jstring server, jstring connect, jint max_size, jint backlog) { // 你的实现逻辑 return 0; } JNIEXPORT void JNICALL native_logging_set_level(JNIEnv *env, jclass clazz, jlong instance_ptr, jint level) { // 你的实现逻辑 } - 在
JNI_OnLoad函数中注册方法映射:static const JNINativeMethod methods[] = { {"logging_new", "(ILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;II)J", (void *)native_logging_new}, {"logging_set_level", "(JI)V", (void *)native_logging_set_level} }; JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv *env; if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } jclass clazz = (*env)->FindClass(env, "examples/logging/FastLogging"); if (clazz == NULL) { return JNI_ERR; } if ((*env)->RegisterNatives(env, clazz, methods, sizeof(methods)/sizeof(methods[0])) < 0) { return JNI_ERR; } return JNI_VERSION_1_6; }
这种方式下,Java方法名无需修改,也能正常和JNI函数绑定。
- 编写JNI实现函数时自定义函数名,比如:
内容的提问来源于stack exchange,提问作者Martin Bammer
相关产品推荐
相关产品推荐

