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

使用JNA创建共享内存写入时触发java.lang.Error: Invalid memory access错误的求助

解决JNA创建共享内存时的Invalid memory access错误

我看到你在使用JNA创建Windows共享内存时触发了Invalid memory access错误,这个问题的核心原因是调用MapViewOfFile时传入了错误的权限参数。

问题根源

你代码里的这一行:

SharedMemoryData = myKernel32.MapViewOfFile(SharedMemoryHandle, PAGE_READWRITE, 0, 0, SharedMemorySize);

这里第二个参数用了PAGE_READWRITE,但这个常量是给CreateFileMapping用的内存页保护属性,而MapViewOfFile的第二个参数需要的是文件映射的访问权限常量,比如FILE_MAP_WRITE、FILE_MAP_READ或者FILE_MAP_ALL_ACCESS。传入错误的参数会导致映射的内存没有写入权限,所以执行setByte时会触发内存访问错误。

修复步骤

  1. 首先需要导入正确的权限常量,在你的import里添加:
import static com.sun.jna.platform.win32.WinNT.FILE_MAP_ALL_ACCESS;
  1. 修改MapViewOfFile的调用,把第二个参数替换为FILE_MAP_ALL_ACCESS(或者根据需求用FILE_MAP_WRITE):
SharedMemoryData = myKernel32.MapViewOfFile(SharedMemoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, SharedMemorySize);

另外,建议你添加错误排查逻辑,调用GetLastError来获取具体的系统错误码,方便定位问题,比如:

if (SharedMemoryHandle == null) {
    System.err.println("CreateFileMapping failed, error: " + myKernel32.GetLastError());
    return;
}
if (SharedMemoryData == null) {
    System.err.println("MapViewOfFile failed, error: " + myKernel32.GetLastError());
    return;
}

完整的可运行示例

下面是包含资源释放逻辑的完整代码,避免内存泄漏:

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.Kernel32;
import static com.sun.jna.platform.win32.WinBase.INVALID_HANDLE_VALUE;
import com.sun.jna.platform.win32.WinNT;
import static com.sun.jna.platform.win32.WinNT.PAGE_READWRITE;
import static com.sun.jna.platform.win32.WinNT.FILE_MAP_ALL_ACCESS;
import com.sun.jna.win32.W32APIOptions;

public class SharedMemoryTest {
    private final MyKernel32 myKernel32;
    private Pointer sharedMemoryData;
    private WinNT.HANDLE sharedMemoryHandle;

    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = (MyKernel32) Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
    }

    public SharedMemoryTest() {
        myKernel32 = MyKernel32.INSTANCE;
    }

    public void test() {
        String sharedMemoryName = "SomeSharedMemory";
        int sharedMemorySize = 128;

        // 创建文件映射对象
        sharedMemoryHandle = myKernel32.CreateFileMapping(
                (WinNT.HANDLE) INVALID_HANDLE_VALUE,
                null,
                PAGE_READWRITE,
                0,
                sharedMemorySize,
                sharedMemoryName
        );
        if (sharedMemoryHandle == null) {
            System.err.println("CreateFileMapping failed, error code: " + myKernel32.GetLastError());
            return;
        }

        // 映射视图到进程地址空间
        sharedMemoryData = myKernel32.MapViewOfFile(
                sharedMemoryHandle,
                FILE_MAP_ALL_ACCESS,
                0,
                0,
                sharedMemorySize
        );
        if (sharedMemoryData == null) {
            System.err.println("MapViewOfFile failed, error code: " + myKernel32.GetLastError());
            myKernel32.CloseHandle(sharedMemoryHandle);
            return;
        }

        // 读写共享内存
        System.out.println("初始值: " + sharedMemoryData.getByte(0));
        sharedMemoryData.setByte(0, (byte) 2);
        System.out.println("写入后的值: " + sharedMemoryData.getByte(0));

        // 释放资源
        myKernel32.UnmapViewOfFile(sharedMemoryData);
        myKernel32.CloseHandle(sharedMemoryHandle);
    }

    public static void main(String[] args) {
        new SharedMemoryTest().test();
    }
}

额外注意事项

  • 记得在使用完共享内存后调用UnmapViewOfFile和CloseHandle释放资源,避免内存泄漏。
  • 如果是跨进程访问,确保其他进程使用相同的共享内存名称,并且映射时使用对应的访问权限。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 07:22:37