Java中用MappedByteBuffer实现多进程共享内存,本质是通过文件映射让多个JVM进程访问同一块操作系统页缓存,需用RandomAccessFile获取READ_WRITE通道、统一文件路径与映射区间,并调用force()保障可见性。

Java 中用 MappedByteBuffer 实现多进程共享内存,本质是**通过文件映射让多个 JVM 进程访问同一块操作系统页缓存**,而非真正无文件的“命名共享内存”。它不依赖 socket 或管道,延迟低、吞吐高,但需注意同步、可见性和资源管理。
必须用 RandomAccessFile 获取可读写通道
只有 RandomAccessFile 打开的 FileChannel 才支持 READ_WRITE 模式映射。用 FileInputStream 或 FileOutputStream 构造的通道无法双向映射,会抛异常。
- 正确写法:
RandomAccessFile raf = new RandomAccessFile("shm.dat", "rw"); FileChannel fc = raf.getChannel(); - 映射前建议调用
fc.truncate(size)或raf.setLength(size)确保文件有足够空间,避免IOException - 映射后务必在进程退出前关闭
raf(或用 try-with-resources),否则文件句柄和内存映射可能残留
映射同一文件路径 + 相同区间
多个 Java 进程要共享数据,必须:
- 使用完全相同的文件路径(如
"./shared.mem"),路径需可被所有进程访问(避免相对路径歧义) - 映射相同起始偏移(通常是
0)和相同长度(如4096字节) - 统一使用
FileChannel.MapMode.READ_WRITE——READ_ONLY进程无法感知其他进程写入,PRIVATE是写时复制,不共享修改
手动保障数据可见性与同步
MappedByteBuffer 的写操作不自动对其他进程可见,JVM 内存模型也不约束堆外内存。不能靠 volatile 或 synchronized 解决跨进程可见性。
立即学习“Java免费学习笔记(深入)”;
- 写入关键数据后,调用
buffer.force()强制刷入 OS 页缓存(不保证立即落盘,但提升另一进程读到新值的概率) - 推荐用“状态标志位”协议:例如约定字节 0 为控制位,写方完成数据写入后设为
1;读方轮询该字节,直到值变为1再读主体数据 - 避免跨进程使用
asCharBuffer()、asIntBuffer()等视图 —— 字节序、对齐方式可能因 JVM 实现或平台不同而错位
跨语言共享(如 Java ↔ C++)需额外适配
纯 Java 多进程可用文件映射,但若要与 C++/C# 共享,需注意:
- Windows 下 C++ 常用
CreateFileMapping(INVALID_HANDLE_VALUE)创建无文件的命名共享内存,Java 无法直接对接 —— 必须改用CreateFileMapping映射到实际文件(如"\\.\Global\MyShm"不行,得用"shm.bin") - 推荐统一走文件映射路径,并约定结构体布局(如固定偏移+小端序+无 padding)
- 必要时用 JNI/JNA 调用系统 API,但会牺牲跨平台性


















