Netty架构 - nio - 内存映射文件

Memory Mapped File

在java早期版本中,使用FileSystem传统的API来访问系统文件。这种场景下,JVM发起read()、write()系统调用从OS kernel到JVM传输数据。JVM使用它的内存空间加载、处理文件。如果文件比较大,处理起来比较慢。OS使用的方式处理文件,而JVM使用字节流的方式,不能匹配文件页,因此需要从OS内核空间拷贝文件的内容到JVM空间。从jdk1.4开始,提供了MappedByteBuffer,用于帮助建立一个从JVM空间到OS文件系统页的映射的虚拟内存。这种方式避免了因为拷贝文件内容的带来的开销。OS使用虚拟内存在内核空间之外缓存文件,可以被非内核进行所共享。java直接映射文件页到MappedByteBuffer,然后处理文件,不需要将其加载到JVM里面。请添加图片描述

MappedByteBuffer直接使用FileChannelmap方法,对虚拟内存的内容进行映射。MappedByteBuffer对象工作起来像buffer,但是它的数据存储在虚拟内存的文件里。get()方法可以从文件里获取数据。put()方法更新数据,对文件的其他读者修改可见。

这样做的好处,如下:

  • JVM直接在虚拟内存上处理,不需要发起read()、write()系统调用。
  • JVM不需要在它的内存空间中加载文件,处理大数据文件更有效率。
  • OS基本上只需要关注虚拟内存的读写,不需要使用JVM。
  • 提供文件的部分映射。
  • 虚拟内存的文件数据不需要buffer进行传递。

在这里插入图片描述

在这里插入图片描述

如果增加了准备写入的文件大小,并且大于了文件本身的大小,导致MappedByteBuffer 在写模式中匹配的大小变得更大,但是在读模式中会抛出IOException。

提供了如下三种映射模式:

  • READ_ONLY: Read only
  • READ_WRITE: Read and update the file
  • PRIVATE: Change in MappedByteBuffer will not reflect to File.

映射同一个文件的多个MappedByteBuffer之间不可见可以通过PRIVATE映射模式,创建私有的副本。

如果在READ_ONLY模式中写,会抛出NonWritableChannelException。如果读取的channel没有开放,此时的读取会抛出NonReadableChannelException。

e.g.

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章