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

Win7 64位下JNA调用SiUSBXp.dll遇内存访问无效等问题求助

解决64位JVM下JNA调用SiUSBXp.dll的内存访问异常与返回值错误问题

问题背景

之前我在32位环境下用JNA 4.1.0调用32位编译的SiUSBXp.dll,搭配32位JVM运行完全正常。最近升级到64位Windows 7系统后,换成64位JVM(jdk1.8.0_151)和64位版本的DLL,USB收发数据时碰到了一堆棘手的问题:

  • Java应用时不时抛出Invalid memory access异常
  • 使用IntByReference接收返回值时,得到的是完全不符合预期的数值(比如返回-134127606而不是预期的3)

这些问题在32位环境里从来没出现过,而且我用C++测试64位DLL时完全正常,甚至换成JNA 4.5.0也还是会触发内存访问异常。

问题函数签名

引发问题的C++函数签名是:

SI_STATUS SI_Write ( HANDLE Handle, LPVOID Buffer, DWORD NumBytesToWrite, DWORD *NumBytesWritten, OVERLAPPED *o = NULL );

我之前在Java里用了两种声明,32位下都能正常工作:

int SI_Write (HANDLE Handle, byte[] lpBuffer, int dwBytesToWrite, IntByReference lpdwBytesWritten);
int SI_Write (HANDLE Handle, Pointer lpBuffer, int dwBytesToWrite, IntByReference lpdwBytesWritten);

调用示例代码

我当时的调用代码大概是这样的:

int dwBytesWritten = 0;
int size = 3;
byte[] buf_w= new byte[size];
IntByReference IBR_BytesWritten = new IntByReference();
IBR_BytesWritten.setValue(dwBytesWritten);

buf_w[0] = FT_WRITE_MSG;
buf_w[1] = (byte)(size & 0x000000FF);
buf_w[2] = (byte)((size & 0x0000FF00) >> 8);

Pointer ptr = new Memory(buf_w.length);
ptr.write(0, buf_w, 0, buf_w.length);

status = SiUSBXp.INSTANCE.SI_Write(dev_handle_ref.getValue(), ptr, size, IBR_BytesWritten);

不管是传Pointer还是直接传byte[],运行几次后要么抛内存访问异常,要么IBR_BytesWritten.getValue()返回错误值。

解决方案

最后发现问题出在默认参数的处理上!虽然C++里OVERLAPPED *o参数默认是NULL,但64位JNA调用时不能省略这个参数,必须显式声明并传入空指针。

修改后的Java函数签名:

int SI_Write (HANDLE Handle, byte[] lpBuffer, int dwBytesToWrite, IntByReference lpdwBytesWritten, Pointer overlapped);

调用的时候直接传null作为最后一个参数:

status = SiUSBXp.INSTANCE.SI_Write(dev_handle_ref.getValue(), buf_w, size, IBR_BytesWritten, null);

这样就彻底解决了内存访问异常和返回值错误的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:56:02