文章目录

  • 简介
  • 虚拟地址空间
  • 详解MappedByteBuffer
    • MapMode
  • MappedByteBuffer的最大值
  • MappedByteBuffer的使用
  • MappedByteBuffer要注意的事项
  • 总结

简介

大大大,我要大!小师妹要读取的文件越来越大,该怎么帮帮她,让程序在性能和速度上面得到平衡呢?快来跟F师兄一起看看吧。

虚拟地址空间

小师妹:F师兄,你有没有发现,最近硬盘的价格真的是好便宜好便宜,1T的硬盘大概要500块,平均1M五毛钱。现在下个电影都1G起步,这是不是意味着我们买入了大数据时代?

没错,小师妹,硬件技术的进步也带来了软件技术的进步,两者相辅相成,缺一不可。

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

小师妹:F师兄,如果要是去读取G级的文件,有没有什么快捷简单的方法?

还记得上次我们讲的虚拟地址空间吗?

再把上次讲的图搬过来:

通常来说我们的应用程序调用系统的接口从磁盘空间获取Buffer数据,我们把自己的应用程序称之为用户空间,把系统的底层称之为系统空间。

传统的IO操作,是操作系统讲磁盘中的文件读入到系统空间里面,然后再拷贝到用户空间中,供用户使用。

这中间多了一个Buffer拷贝的过程,如果这个量够大的话,其实还是挺浪费时间的。

于是有人在想了,拷贝太麻烦太耗时了,我们单独划出一块内存区域,让系统空间和用户空间同时映射到同一块地址不就省略了拷贝的步骤吗?

这个被划出来的单独的内存区域叫做虚拟地址空间,而不同空间到虚拟地址的映射就叫做Buffer Map。 Java中是有一个专门的MappedByteBuffer来代表这种操作。

小师妹:F师兄,那这个虚拟地址空间和内存有什么区别呢?有了内存还要啥虚拟地址空间?

虚拟地址空间有两个好处。

第一个好处就是虚拟地址空间对于应用程序本身而言是独立的,从而保证了程序的互相隔离和程序中地址的确定性。比如说一个程序如果运行在虚拟地址空间中,那么它的空间地址是固定的,不管他运行多少次。如果直接使用内存地址,那么可能这次运行的时候内存地址可用,下次运行的时候内存地址不可用,就会导致潜在的程序出错。

第二个好处就是虚拟空间地址可以比真实的内存地址大,这个大其实是对内存的使用做了优化,比如说会把很少使用的内存写如磁盘,从而释放出更多的内存来做更有意义的事情,而之前存储到磁盘的数据,当真正需要的时候,再从磁盘中加载到内存中。

这样物理内存实际上可以看做虚拟空间地址的缓存。

详解MappedByteBuffer

小师妹:MappedByteBuffer听起来好神奇,怎么使用它呢?

我们先来看看MappedByteBuffer的定义:

public abstract class MappedByteBufferextends ByteBuffer

它实际上是一个抽象类,具体的实现有两个:

class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer
class DirectByteBufferR extends DirectByteBuffer
implements DirectBuffer

分别是DirectByteBuffer和DirectByteBufferR。

小师妹:F师兄,这两个ByteBuffer有什么区别呢?这个R是什么意思?

R代表的是ReadOnly的意思,可能是因为本身是个类的名字就够长了,所以搞了个缩写。但是也不写个注解,让人看起来十分费解…

我们可以从RandomAccessFile的FilChannel中调用map方法获得它的实例。

我们看下map方法的定义:

 public abstract MappedByteBuffer map(MapMode mode, long position, long size)throws IOException;

MapMode代表的是映射的模式,position表示是map开始的地址,size表示是ByteBuffer的大小。

MapMode

小师妹:F师兄,文件有只读,读写两种模式,是不是MapMode也包含这两类?

对的,其实NIO中的MapMode除了这两个之外,还有一些其他很有趣的用法。

  • FileChannel.MapMode.READ_ONLY 表示只读模式
  • FileChannel.MapMode.READ_WRITE 表示读写模式
  • FileChannel.MapMode.PRIVATE 表示copy-on-write模式,这个模式和READ_ONLY有点相似,它的操作是先对原数据进行拷贝,然后可以在拷贝之后的Buffer中进行读写。但是这个写入并不会影响原数据。可以看做是数据的本地拷贝,所以叫做Private。

基本的MapMode就这三种了,其实除了基础的MapMode,还有两种扩展的MapMode:

  • ExtendedMapMode.READ_ONLY_SYNC 同步的读
  • ExtendedMapMode.READ_WRITE_SYNC 同步的读写

MappedByteBuffer的最大值

小师妹:F师兄,既然可以映射到虚拟内存空间,那么这个MappedByteBuffer是不是可以无限大?

当然不是了,首先虚拟地址空间的大小是有限制的,如果是32位的CPU,那么一个指针占用的地址就是4个字节,那么能够表示的最大值是0xFFFFFFFF,也就是4G。

另外我们看下map方法中size的类型是long,在java中long能够表示的最大值是0x7fffffff,也就是2147483647字节,换算一下大概是2G。也就是说MappedByteBuffer的最大值是2G,一次最多只能map 2G的数据。

MappedByteBuffer的使用

小师妹,F师兄我们来举两个使用MappedByteBuffer读写的例子吧。

善!

先看一下怎么使用MappedByteBuffer来读数据:

public void readWithMap() throws IOException {try (RandomAccessFile file = new RandomAccessFile(new File("src/main/resources/big.www.flydean.com"), "r")){//get ChannelFileChannel fileChannel = file.getChannel();//get mappedByteBuffer from fileChannelMappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());// check bufferlog.info("is Loaded in physical memory: {}",buffer.isLoaded());  //只是一个提醒而不是guaranteelog.info("capacity {}",buffer.capacity());//read the bufferfor (int i = 0; i < buffer.limit(); i++){log.info("get {}", buffer.get());}}}

然后再看一个使用MappedByteBuffer来写数据的例子:

public void writeWithMap() throws IOException {try (RandomAccessFile file = new RandomAccessFile(new File("src/main/resources/big.www.flydean.com"), "rw")){//get ChannelFileChannel fileChannel = file.getChannel();//get mappedByteBuffer from fileChannelMappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096 * 8 );// check bufferlog.info("is Loaded in physical memory: {}",buffer.isLoaded());  //只是一个提醒而不是guaranteelog.info("capacity {}",buffer.capacity());//write the contentbuffer.put("www.flydean.com".getBytes());}}

MappedByteBuffer要注意的事项

小师妹:F师兄,MappedByteBuffer因为使用了内存映射,所以读写的速度都会有所提升。那么我们在使用中应该注意哪些问题呢?

MappedByteBuffer是没有close方法的,即使它的FileChannel被close了,MappedByteBuffer仍然处于打开状态,只有JVM进行垃圾回收的时候才会被关闭。而这个时间是不确定的。

总结

本文再次介绍了虚拟地址空间和MappedByteBuffer的使用。

本文的例子https://github.com/ddean2009/learn-java-io-nio

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/io-nio-mappedbytebuffer/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

小师妹学JavaIO之:MappedByteBuffer多大的文件我都装得下相关推荐

  1. mappedbytebuffer_小师妹学JavaIO之:MappedByteBuffer多大的文件我都装得下

    简介 大大大,我要大!小师妹要读取的文件越来越大,该怎么帮帮她,让程序在性能和速度上面得到平衡呢?快来跟F师兄一起看看吧. 虚拟地址空间 小师妹:F师兄,你有没有发现,最近硬盘的价格真的是好便宜好便宜 ...

  2. 小师妹学JavaIO之:文件写入那些事

    文章目录 简介 字符输出和字节输出 格式化输出 输出其他对象 在特定的位置写入 给文件加锁 总结 简介 小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么? ...

  3. .dat文件写入byte类型数组_小师妹学JavaIO之:文件写入那些事

    简介 小师妹又对F师兄提了一大堆奇奇怪怪的需求,要格式化输出,要特定的编码输出,要自己定位输出,什么?还要阅后即焚?大家看F师兄怎么一一接招吧. 字符输出和字节输出 小师妹:F师兄,上次你的IO讲到了 ...

  4. 小师妹学JavaIO之:Buffer和Buff

    文章目录 简介 Buffer是什么 Buffer进阶 创建Buffer Direct VS non-Direct Buffer的日常操作 向Buffer写数据 从Buffer读数据 rewind Bu ...

  5. 小师妹学JavaIO之:try with和它的底层原理

    文章目录 简介 IO关闭的问题 使用try with resource try with resource的原理 自定义resource 总结 简介 小师妹是个java初学者,最近正在学习使用java ...

  6. 小师妹学JavaIO之:文件读取那些事

    文章目录 简介 字符和字节 按字符读取的方式 按字节读取的方式 寻找出错的行数 总结 简介 小师妹最新对java IO中的reader和stream产生了一点点困惑,不知道到底该用哪一个才对,怎么读取 ...

  7. java buff_小师妹学JavaIO之:Buffer和Buff

    简介 小师妹在学习NIO的路上越走越远,唯一能够帮到她的就是在她需要的时候给她以全力的支持.什么都不说了,今天介绍的是NIO的基础Buffer.老铁给我上个Buff. Buffer是什么 小师妹:F师 ...

  8. 小师妹学JavaIO之:用Selector来发好人卡

    文章目录 简介 Selector介绍 创建Selector 注册Selector到Channel中 SelectionKey selector 和 SelectionKey 总的例子 总结 简介 NI ...

  9. 小师妹学JavaIO之:NIO中那些奇怪的Buffer

    文章目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,B ...

最新文章

  1. 【arduino】ESP32 SPIFFS插件使用报错及解决方法:SPIFFS Error:esptool not found!
  2. 克莱姆森大学计算机排名,克莱姆森大学计算机科学computer science专业排名第401~500名(2020THE泰晤士高等教育世界大学排名)...
  3. sql server2008给数据表,字段,添加修改注释
  4. 使用log4j监视和筛选应用程序日志到邮件
  5. 更新SQL Server实例所有数据库表统计信息
  6. 在Linux中模拟击键和鼠标移动
  7. asp.net调用js方法小结
  8. 一个老程序员对数据库的一点纠结
  9. L1-003. 个位数统计-PAT团体程序设计天梯赛GPLT
  10. linux下qemu共享文件夹,QEMU Windows来宾和Linux主机之间的共享文件夹
  11. JVM GC调优一则--增大Eden Space提高性能
  12. JavaEE学习11--数据库语言SQL
  13. 记录一次由于流的read(byte[3 * 1024], 0, len); 读取不足定义的长度,引发的线上bug
  14. mysql 查看二进制_查看mysql二进制文件(binlog文件)
  15. try catch finally 执行简介
  16. 精品软件 推荐 电子书转换器 EPUB to PDF Converter
  17. c语言用数字代表字母,使用c语言判断数字字母
  18. MultiSigWallet实例
  19. C# 3GQQ批量登录工具(QQ答复机器人)
  20. ubuntu系统安装时的分区方案

热门文章

  1. RelationTrack解读
  2. FZU1969(最大公约数之和)
  3. HDU1058 Humble Numbers
  4. 外挂学习之路(15)---lua语言的使用,
  5. MFC中动态数组CArray的使用
  6. C++设计模式之桥接模式
  7. 趣谈设计模式 | 外观模式(Facade):为子系统提供高粒度接口
  8. 实战:如何对磁盘和网络IO进行评估、监控、定位和优化?
  9. 扔掉,MySQL!性能被 MariaDB 吊打…
  10. Go 应用性能优化指北