自定义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
相关产品推荐
相关产品推荐

