首页 > 解决方案 > 我可以使用 java 内存映射文件 (MappedByteBuffer) 处理大于系统内存的文件吗?

问题描述

  1. MappedByteBuffer 是如何工作的?当我像这样创建一个 MappedByteBuffer 对象时:</li>
RandomAccessFile in = new RandomAccessFile("./src/test.txt", "rw");
FileChannel Fcin = in.getChannel(); 
MappedByteBuffer mapBuff = Fcin.map(FileChannel.MapMode.READ_WRITE, 0, 0xFFFF);

这是否意味着 MappedByteBuffer 对象包含该文件的所有内容?

2.如果1的答案是YES,这句话在Thinking in Java (page 692)中如何解释?

内存映射文件允许您创建和修改太大而无法放入内存的文件

3.当isLoaded()的返回值对一个MappedByteBuffer对象为真时是什么意思?

标签: javamemory-mapped-files

解决方案


有很多问题,但都是相关的,所以我将尝试全部回答:

我可以使用 java 内存映射文件 (MappedByteBuffer) 处理大于系统内存的文件吗?

在使用虚拟内存的最新操作系统(实际上我知道的所有当前操作系统)上,答案是肯定的,你可以

MappedByteBuffer 是如何工作的?

这在很大程度上取决于底层操作系统如何处理内存映射文件。大多数时候,它声明了一堆映射到文件内容的虚拟内存。这意味着MappedByteBuffer包含文件数据的映像,但某些页面可能没有映射到物理内存(即:实际数据仅在磁盘文件上)

这是否意味着 MappedByteBuffer 对象包含该文件的所有内容?

是的。至少实际上是因为数据可以按需加载到内存中。

如果 1 的答案是 YES,那么 Thinking in Java 如何解释这句话...

借助虚拟内存,当您处理大于可用内存的文件时,大部分数据仍保留在磁盘上。如果您尝试访问当前未映射的数据,则虚拟内存系统将(最终丢弃一些其他内存页面并)将包含请求数据的页面映射到物理内存页面以(几乎)透明地访问该数据。

当 isLoaded() 的返回值对 MappedByteBuffer 对象为真时,这意味着什么?

这暗示缓冲区的全部内容都驻留在物理内存中。但是 Javadoc 清楚地表明它不是保证,它严重依赖于操作系统。

长话短说,内存映射文件是一个很好的工具,它允许处理磁盘文件,就好像它是一个(可能是巨大的)字节数组一样。可能的缺点是它很容易创建性能很差的程序,因为整个磁盘 IO 对程序员是隐藏的,就像系统花时间将内存页面存储到磁盘并再次加载它们时一样。最后,您可能有一个看起来像内存的漂亮缓冲区,但具有磁盘 IO 访问时间。

我的建议是,在使用它之前,程序员应该想知道所涉及的磁盘 IO 是什么。在某些用例中,它会比手动读取和处理文件更快,因为所有访问都保证是页面对齐的,而在其他用例中,这将是一场灾难,因为非连续访问将需要大量的磁盘访问。


推荐阅读