You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin JNI加载库正常但调用外部函数报UnsatisfiedLinkError

根因

该问题是**C++ 名字修饰(Name Mangling)**导致的JNI符号匹配失败:

  • JVM查找native方法实现时,会按照JNI约定的C风格命名规则匹配动态库导出符号,即无编译器额外修饰的Java_包名_类名_方法名格式符号。
  • 从nm输出可见,startProxy对应的导出符号是__Z51Java_abc_de_fg_jni_ProxyControls_startProxyP7JNIEnv_P8_jobject,前缀_Z是C编译器对函数名做修饰后的典型特征:C为了支持函数重载等特性,会在编译时修改函数名、把参数类型信息编码到符号名里,最终导出的符号不符合JNI的命名匹配规则。
  • JNI_OnLoad能被正常调用是因为它的导出符号是未被修饰的_JNI_OnLoad,符合动态库入口的查找规则,因此库加载流程无异常,但JVM始终找不到匹配startProxy的正确符号,调用时就会抛出UnsatisfiedLinkError。
修复方案
  • 对所有JNI导出的函数添加extern "C"声明,告诉C++编译器按照C语言的规则导出这些函数,不做名字修饰。
    可以用块统一包裹所有JNI实现:
    extern "C" {
    JNIEXPORT void JNICALL
    Java_abc_de_fg_jni_ProxyControls_startProxy(JNIEnv *env, jobject obj) {
        // 原有业务实现
    }
    
    // 其余JNI方法统一放在该块内即可
    }
    
    也可以单独给单个函数加声明:
    extern "C" JNIEXPORT void JNICALL
    Java_abc_de_fg_jni_ProxyControls_startProxy(JNIEnv *env, jobject obj);
    
  • 重新编译动态库后,用nm命令验证导出符号,此时startProxy对应的导出符号应该为_Java_abc_de_fg_jni_ProxyControls_startProxy(无_Z前缀的修饰内容,macOS平台C符号默认带前导下划线属于正常情况,JVM会自动处理),此时JVM即可正常匹配到native实现,调用不再报错。

内容的提问来源于stack exchange,提问作者Shazniq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 11:15:29