使用JNA调用C#时出现java.lang.Error: Invalid memory access错误求助
Java通过JNA调用C#程序时触发
java.lang.Error: Invalid memory access错误 错误信息
java.lang.Error: Invalid memory access
相关代码(64位环境)
C#代码
namespace EwpDeleteBlank { public static class RemoveBlankPage { } }
C++头文件(pch.h)
#ifndef PCH_H #define PCH_H #include "framework.h" #include <string> using namespace std; #define MYLIBAPI extern "C" __declspec(dllexport) MYLIBAPI void deleteBlankPages(); #endif //PCH_H
C++实现文件(pch.cpp)
#include "pch.h" #include <string> #using "C:\\Users\\zhang\\Desktop\\g\\ewp-delete-blank\\bin\\x64\\Debug\\RemoveBlankPage.dll" using namespace EwpDeleteBlank; using namespace std; void deleteBlankPages() { RemoveBlankPage ^obj = gcnew RemoveBlankPage(); }
Java代码
public interface MyLibraryInterface extends Library { MyLibraryInterface instance = (MyLibraryInterface) Native.loadLibrary("Dll1.dll", MyLibraryInterface.class); void deleteBlankPages(); } // 调用代码 MyLibraryInterface.instance.deleteBlankPages();
问题原因
- 托管与非托管兼容性冲突:你的C代码使用了
#using托管DLL、gcnew等CLR特性,编译出的Dll1.dll是托管C DLL,而JNA仅支持调用纯原生非托管C/C++ DLL,两者的内存模型、调用约定完全不同,直接调用必然触发内存访问错误。 - C#静态类实例化错误:
RemoveBlankPage是C#静态类,静态类不允许被实例化,gcnew RemoveBlankPage()本身就是非法操作,会触发CLR内部异常,进而传递给JNA导致内存访问报错。
解决方案
方案1:直接导出C#方法供JNA调用(推荐)
借助UnmanagedExports NuGet包,直接将C#方法导出为原生函数,无需C++中间层:
- 在C#项目中安装
UnmanagedExportsNuGet包。 - 修改C#代码:
namespace EwpDeleteBlank { public class RemoveBlankPage { [DllExport("deleteBlankPages", CallingConvention = CallingConvention.Cdecl)] public static void DeleteBlankPages() { // 编写业务逻辑 } } }
- 编译生成64位C# DLL,Java端直接用JNA调用该DLL即可。
方案2:用COM方式实现C++与C#交互
如果必须保留C++中间层,需通过COM接口调用C#:
- 给C#类添加
[ComVisible(true)]属性,在项目属性中勾选“为COM互操作注册”,将C#类注册为COM组件。 - 在C++代码中通过COM接口调用C#方法,编译为纯原生非托管DLL。
- Java端用JNA调用这个原生DLL。
方案3:修正基础代码错误(不推荐)
如果坚持使用C++/CLR中间层:
- 将C#的静态类改为普通类:
namespace EwpDeleteBlank { public class RemoveBlankPage { } }
- 确保C++项目编译为支持CLR的DLL,同时保证Java与DLL的架构一致(均为64位)。但这种方式本质仍为托管DLL,JNA调用仍可能存在兼容性问题。
内容的提问来源于stack exchange,提问作者marlon
相关产品推荐
相关产品推荐

