温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

java nio内存映射怎么用

发布时间:2026-09-02 13:39:12 来源:亿速云 阅读:91 作者:小樊 栏目:编程语言

Java NIO 的内存映射文件(Memory-Mapped File)是通过 FileChannel.map() 把磁盘文件的一部分或全部直接映射到内存中,程序可以像访问普通内存一样读写文件,适合大文件、高性能 IO场景。

下面从 概念 → 用法 → 示例 → 注意事项 给你讲清楚。


一、核心类

java.nio.channels.FileChannel
java.nio.MappedByteBuffer

映射模式(FileChannel.MapMode):

模式 说明
READ_ONLY 只读映射
READ_WRITE 读写映射(会写回文件)
PRIVATE 写时复制(不影响文件)

二、基本使用步骤

  1. 打开文件 FileChannel
  2. 调用 map() 得到 MappedByteBuffer
  3. 像普通 ByteBuffer 一样读写
  4. 关闭 channel(映射由 JVM / OS 管理)

三、简单示例

1️⃣ 写文件(内存映射)

import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

public class MmapWrite {
    public static void main(String[] args) throws Exception {
        RandomAccessFile file = new RandomAccessFile("test.txt", "rw");
        FileChannel channel = file.getChannel();

        // 映射 0~1024 字节
        MappedByteBuffer buffer =
                channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);

        buffer.put("Hello MappedByteBuffer".getBytes());

        channel.close();
        file.close();
    }
}

2️⃣ 读文件(内存映射)

RandomAccessFile file = new RandomAccessFile("test.txt", "r");
FileChannel channel = file.getChannel();

MappedByteBuffer buffer =
        channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());

byte[] data = new byte[buffer.remaining()];
buffer.get(data);

System.out.println(new String(data));

四、为什么快?

✅ 减少 内核态 ↔ 用户态 拷贝
✅ 利用 OS 的 页缓存(page cache)
✅ 随机访问大文件效率高

适合:

  • 大文件处理
  • 消息队列 / 日志系统
  • 数据库 / 搜索引擎

五、重要注意事项(很容易踩坑)

⚠️ 1. MappedByteBuffer 不会被 GC 立即释放

  • 映射内存由操作系统管理
  • buffer = null + System.gc() 不保证释放
  • 大量映射文件可能导致:
    java.io.IOException: Map failed
    

✅ 解决方案:

  • 控制映射文件数量
  • 映射小文件分块
  • 使用 Cleaner(反射或第三方库)

示例(强制释放,谨慎使用):

Method cleaner = buffer.getClass().getMethod("cleaner");
cleaner.setAccessible(true);
Object clean = cleaner.invoke(buffer);
Method cleanMethod = clean.getClass().getMethod("clean");
cleanMethod.invoke(clean);

⚠️ 2. 文件大小不能动态增长

映射时大小是固定的:

channel.map(mode, position, size);

要扩大文件:

file.setLength(newSize);

⚠️ 3. Windows 下文件被占用

  • 映射后文件无法删除
  • 必须释放映射才能删

六、常见使用模式

分块映射大文件

long fileSize = channel.size();
long chunk = 1024 * 1024; // 1MB

for (long pos = 0; pos < fileSize; pos += chunk) {
    long size = Math.min(chunk, fileSize - pos);
    MappedByteBuffer buf =
        channel.map(READ_ONLY, pos, size);
    // 处理 buf
}

七、总结一句话

Java NIO 内存映射 = 把文件当内存用,快但难管。

如果你愿意,我也可以帮你:

  • ✅ 写一个“高性能日志写入器”
  • ✅ 对比 MappedByteBuffer vs BufferedInputStream
  • ✅ 解释 Netty / Kafka 怎么用 mmap

你想用在什么场景?

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI