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

自定义Java返回类型调用Go本地方法时出现UnsatisfiedLinkError

问题分析

使用System.loadLibrary配合Java native方法调用Go导出函数时,出现UnsatisfiedLinkError的核心原因是:JNI会按照Java_<包名>_<类名>_<方法名>的固定规则查找本地函数,但Go导出的函数名是GetDetails,不符合JNI的命名规范,导致无法匹配;而JNA的Native.load会直接查找库中导出的原始函数名,因此能正常工作。

解决方案

结合服务要求的System.loadLibrary Runtime加载规则,以及JNA的函数绑定能力,通过“先加载库,再复用已加载实例”的方式解决问题:

1. 保留结构体定义

原GoResult结构体无需修改,确保与Go返回值的结构匹配:

import com.sun.jna.Structure;
import com.sun.jna.Pointer;
import java.util.List;
import java.util.Arrays;

public class GoResult extends Structure implements Structure.ByValue {
    public Pointer p1;
    public Pointer p2;
    public String str;
    public String error;

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList("p1", "p2", "str", "error");
    }
}

2. 定义JNA接口

仅声明接口,不在接口内直接初始化实例,避免提前加载库:

import com.sun.jna.Library;

public interface MyLib extends Library {
    GoResult GetDetails();
}

3. 按服务要求加载并调用

先通过System.loadLibrary加载库,再用Native.loadLibrary复用已加载的库实例:

import com.sun.jna.Native;

public class Action {
    static {
        try {
            // 遵循服务要求,Runtime时加载库
            System.loadLibrary("mydetails");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 复用已加载的库创建JNA接口实例
    private static final MyLib INSTANCE = Native.loadLibrary("mydetails", MyLib.class);

    public void run() {
        GoResult result = INSTANCE.GetDetails();
        // 处理业务逻辑...

        // 注意:释放Go侧分配的内存,避免泄漏
        Native.free(result.p1);
        Native.free(result.p2);
        Native.free(Pointer.nativeValue(result.str));
        Native.free(Pointer.nativeValue(result.error));
    }
}

关键说明

  • Native.loadLibrary会优先复用已通过System.loadLibrary加载的库实例,不会重复加载,完全符合服务的Runtime加载要求。
  • 必须手动释放Go侧通过C.CBytes和C.CString分配的内存,否则会造成内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:10:11