在Kotlin中使用JNI出现UnsatisfiedLinkError问题求助
你遇到的UnsatisfiedLinkError通常是JVM无法找到对应的Native函数实现导致的,即便javah生成的签名看似正确,也可能存在以下几个常见问题:
1. C++函数未禁用名字修饰
C++编译器会对函数名进行**名字修饰(Name Mangling)**以支持重载特性,这会导致编译后的函数名和JNI期望的Java_gg_kapilarny_luakt_LuaScript_initLuaScript完全不一致。
解决方法:用extern "C"包裹JNI函数,强制编译器采用C风格的函数名规则:
extern "C" { JNIEXPORT void JNICALL Java_gg_kapilarny_luakt_LuaScript_initLuaScript(JNIEnv* env, jobject self, jstring script) { // 你的函数实现 } }
2. 动态库未正确加载
Kotlin/JVM在调用Native方法前,必须先加载编译好的动态库(Linux下是.so,Windows是.dll,macOS是.dylib)。如果没有加载库,或者加载路径/库名错误,JVM就找不到对应的函数。
检查点:
- 确保在调用
initLuaScript前执行加载逻辑,比如:init { System.loadLibrary("luakt") // 对应编译出的libluakt.so // 或者用绝对路径加载:System.load("/path/to/libluakt.so") } - 确认库名是否正确(注意Linux/macOS下库名前缀是
lib,加载时不需要写)。
3. 类路径/包名不匹配
javah是基于编译后的class文件生成头文件的,如果Kotlin类gg.kapilarny.luakt.LuaScript的包名、类名发生过修改,或者编译后的class文件路径和javah扫描的路径不一致,会导致生成的签名和实际类不匹配。
检查点:
- 确认Kotlin类的全限定名(包名+类名)和头文件注释里的
Class: gg_kapilarny_luakt_LuaScript完全一致。 - 重新用最新的class文件生成javah头文件,避免旧签名和新代码不匹配。
4. 架构不兼容
如果编译动态库时的目标架构和运行环境的CPU架构不匹配,会导致库无法加载,进而触发UnsatisfiedLinkError。
检查点:
- 比如在x86_64的电脑上运行,但编译的是arm64架构的库;或者Android设备是armv7a,但编译的是arm64-v8a的库。
- 确保编译时指定的架构和运行环境一致。
5. Native方法访问修饰符问题
虽然UnsatisfiedLinkError主要是找不到函数,但如果Kotlin的external方法是private或internal修饰,JVM可能无法正确关联到Native函数(不过这种情况更少见)。建议将external方法改为public:
public external fun initLuaScript(script: String)
内容的提问来源于stack exchange,提问作者Kapilarny YT

