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

使用JNA调用C# DLL触发Invalid memory access错误求助

JNA调用C#导出DLL时出现Invalid memory access的排查方案

以下是几个常见的排查方向,按优先级排序:

  • 参数/返回值类型映射必须完全匹配
    比如C#定义的int _Add(int a, int b),JNA接口里必须对应int _Add(int a, int b),不能出现类型错配(比如把C#的int对应成JNA的long,或者反过来)。如果涉及引用/输出参数,C#的ref int/out int要对应JNA的IntByReference,不能直接传基本类型。示例:

    // 对应C#的void _Add(ref int result, int a, int b)
    void _Add(IntByReference result, int a, int b);
    

    调用时需要实例化IntByReference传入,再通过getValue()获取结果。

  • 对齐调用约定
    DllExport默认使用stdcall调用约定,但JNA默认用cdecl。必须在JNA加载DLL时显式指定匹配的调用约定:

    public interface MyDll extends Library {
        MyDll INSTANCE = Native.load("YourDllName", MyDll.class,
            Map.of(Library.OPTION_CALLING_CONVENTION, CallingConvention.STDCALL));
        
        int _Add(int a, int b);
    }
    

    如果你在C#导出时修改了调用约定(比如CallingConvention.Cdecl),JNA这边也要同步改成CallingConvention.CDECL。

  • 核对导出方法的真实名称
    用dumpbin查看导出表时,注意是否存在名字修饰(比如stdcall会生成_Add@8这类带后缀的名称)。如果有修饰,要么在JNA接口里使用全名,要么在C#导出时指定无修饰的名称:

    [DllExport("_Add", CallingConvention = CallingConvention.StdCall)]
    public static int Add(int a, int b)
    {
        return a + b;
    }
    
  • 确保DLL与JVM位数一致
    64位的C# DLL必须搭配64位JVM运行,32位DLL必须搭配32位JVM。位数不匹配会直接触发内存访问错误,这个是高频踩坑点。

  • 复杂类型的内存管理检查
    如果方法涉及字符串、结构体等复杂类型:

    • C#返回字符串时,不能直接返回string,需要用Marshal.AllocHGlobal分配非托管内存,JNA读取后要调用Native.free()释放;
    • 结构体定义必须严格对齐字段顺序、类型和内存布局,C#用[StructLayout(LayoutKind.Sequential)],JNA要对应@Structure.FieldOrder({"field1", "field2"})。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:50:09