Java中声明native方法必须用native关键字且无方法体;JVM据此调用C/C++实现,要求签名严格一致、非private/static,包路径需完整;javah已废弃,改用javac -h生成头文件;加载库需匹配架构、签名及java.library.path;JNI操作对象须用API函数,注意内存与异常管理。

Java里怎么写一个native方法声明
必须用native关键字修饰,且不能有方法体,连花括号都不能写。JVM靠这个标记识别“这活儿得甩给C/C++干”。
- 返回类型、方法名、参数列表要和后续C函数严格一致,包括大小写和下划线规则(比如
Java_com_example_MathUtils_add) - 不能是
private或static(除非配合JNI_OnLoad注册),否则JVM找不到入口 - 如果类在包里,生成头文件时路径必须带完整包名,漏一级就
UnsatisfiedLinkError
javah已被废弃,现在怎么生成JNI头文件
javah从JDK 10起彻底移除,现在统一用javac加-h参数生成头文件,路径指定错一格,C端就编译不过。
- 先编译Java类:
javac -cp . com/example/MathUtils.java - 再生成头:
javac -h jni/ -cp . com.example.MathUtils(注意是点号分隔的类名,不是路径) - 生成的
com_example_MathUtils.h里会包含JNIEXPORT和JNICALL宏,别手动删——它们控制调用约定,删了Windows上直接崩溃
加载动态库时常见UnsatisfiedLinkError原因
错误信息里带no xxx in java.library.path,说明JVM压根没找到你的.dll(Windows)、.so(Linux)或.dylib(macOS)。
- 确保
System.loadLibrary("xxx")中的名字不带前缀和后缀(Windows下实际找xxx.dll,不是libxxx.dll) - 路径必须加进
java.library.path:启动时加-Djava.library.path=/path/to/libs,别依赖LD_LIBRARY_PATH或PATH——JVM不认这些 - 32位JVM不能加载64位库,反之亦然;macOS 10.15+默认拒绝未签名的dylib,得用
xattr -d com.apple.quarantine清理隔离属性
C函数里怎么安全访问Java对象字段和数组
不能直接解引用jobject指针,所有操作必须走JNI函数,否则跨GC移动对象时指针立刻失效。
立即学习“Java免费学习笔记(深入)”;
- 读字段用
GetObjectField/GetIntField,先用GetFieldID拿到ID——ID不是常量,每次调用都要查,别缓存到全局变量里(类卸载后ID作废) - 操作数组必须用
GetIntArrayElements+ReleaseIntArrayElements配对,中间不能return或throw异常,否则内存泄漏;更推荐GetIntArrayRegion做拷贝,避免锁住堆内存 - 创建新Java对象要用
NewObject,传入FindClass和GetMethodID结果,别用AllocObject——它不调构造函数,字段全为零值
Exception没清空,下次JNI调用直接失败;又比如把jstring转成C字符串后忘了ReleaseStringUTFChars,字符串常量池慢慢就爆了。这些坑不跑真实负载根本看不出问题。









