可参考: MappedByteBuffer以及ByteBufer的底层原理

概述

Bytebuffer分为两种:间接地和直接的,所谓直接就是指MappedByteBuffer,直接使用内存映射(java的话就意味着在JVM之外分配虚拟地址空间);而间接的ByteBuffer是在JVM的堆上面的。间接缓冲区就是我们通常说的堆缓冲区。
直接缓冲区 java内部是使用 DirectByteBuffer 来实现的。
堆缓冲区java内部是使用 HeapByteBuffer 来实现的。

class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {}class HeapByteBuffer extends ByteBuffer {}

映射的字节缓冲区(MappedByteBuffer ) 不提供关闭或销毁方法。也就是说,创建完直接缓冲区,就一直有效,直到缓冲区本身被垃圾收集。

映射字节缓冲区的内容可以在任何时间改变,例如,如果映射的文件的对应区域的内容由该程序或其他程序改变。无论这种变化是否发生,当它们发生时,都是依赖于操作系统的,因此不明确。

映射的字节缓冲区的全部或部分可能在任何时间变得不可访问,例如映射的文件被截断。试图访问映射字节缓冲区的不可访问区域不会改变缓冲区的内容,并且会导致在访问时或稍后某个时间抛出一个未指定的异常。因此,强烈建议采取适当的预防措施,以避免由该程序或由同时运行的程序操纵映射文件,除了读取或写入文件的内容。

MappedByteBuffer 类结构

public abstract class MappedByteBuffer extends ByteBuffer {public final MappedByteBuffer load( )public final boolean isLoaded( )public final MappedByteBuffer force( )
}

MappedByteBuffer 继承了 ByteBuffer 。

load() 方法

load( )方法会整个文件加载到内存中。

此方法尽最大努力确保当它返回时,该缓冲区的内容驻留在物理内存中。调用此方法可能会导致一些页面错误和I/O操作发生。

操作系统会采用虚拟内存映射,把缓冲区和文件建立虚拟内存映射。此映射使得操作系统的底层虚拟内存子系统可以根据需要将文件中相应区块的数据读进内存。已经在内存中或通过验证的页会占用实际内存空间,并且在它们被读进 RAM 时会挤出最近较少使用的其他内存页。(swap in,swap out)

在一个映射缓冲区上调用 load( )方法会是一个代价高的操作,因为它会导致大量的页调入(page-in),具体数量取决于文件中被映射区域的实际大小。然而,load( )方法返回并不能保证文件就会完全加载到内存,这是由于请求页面调入是动态的。具体结果会因某些因素而有所差异,这些因素包括:操作系统、文件系统,可用 Java 虚拟机内存,最大 Java 虚拟机内存,垃圾收集器实现过程等等。

请小心使用 load( )方法,它可能会导致您不希望出现的结果。该方法的主要作用是为提前加载文件埋单,以便后续的访问速度可以尽可能的快。
对于那些要求近乎实时访问的程序,解决方案就是预加载。但是请记住,不能保证全部页都加载到内存,不管怎样,之后可能还会有页调入发生(操作系统自己维护,依赖操作系统的实现)。内存页什么时候swap in 和 swap out 受多个因素影响,这些因素中的许多都是不受 Java 虚拟机控制的。
JDK 1.4 的 NIO 并没有提供一个可以把页面固定到物理内存上的API,尽管一些操作系统是支持这样做的。对于大多数程序,特别是交互性的或其他事件驱动(event-driven)的程序而言,为提前加载文件消耗资源是不划算的。在实际访问时分摊页调入开销才是更好的选择。让操作系统根据需要来调入页意味着不访问的页永远不需要被加载。同预加载整个被映射的文件相比,这很容易减少 I/O 活动总次数。操作系统已经有一个复杂的内存管理系统了,就让它来替您完成此工作吧!

isLoaded() 方法

我们可以通过调用 isLoaded( )方法来判断一个被映射的文件是否完全加载内存了。
如果该方法返回ture,意味着该缓冲区中的所有数据很可能完全加载到物理内存中了,因此可以在不产生任何虚拟内存页错误或I/O操作的情况下访问。
不过,该方法返回false,并不一定意味着缓冲区的内容没有加载到物理内存中。

返回值是一个提示,而不是一个保证,因为底层操作系统在调用该方法返回的时候可能已经分出了一些缓冲区的数据。

force() 方法

该方法会强制将此缓冲区上的任何更改写入映射到永久磁盘存储器上。

如果映射到该缓冲区的文件驻留在本地存储设备上,那么当该方法返回时,它保证对创建的缓冲区进行的所有更改,或者自上次调用该方法后,将被写入该设备。
如果文件不驻留在本地设备上,则不提供这样的保证。

当用 MappedByteBuffer 对象来更新一个文件,您应该总是使用 MappedByteBuffer.force( )而非 FileChannel.force( ),因为通道对象可能
不清楚通过映射缓冲区做出的文件的全部更改。MappedByteBuffer 没有不更新文件元数据的选项——元数据总是会同时被更新的。

如果映射是以 MapMode.READ_ONLY 或 MAP_MODE.PRIVATE 模式建立的,那么调用 force( )
方法将不起任何作用,因为永远不会有更改需要应用到磁盘上(但是这样做也是没有害处的)。


想了解更多精彩内容请关注我的公众号

本人简书blog地址:http://www.jianshu.com/u/1f0067e24ff8    
点击这里快速进入简书
GIT地址:http://git.oschina.net/brucekankan/
点击这里快速进入GIT

NIO 之 MappedByteBuffer相关推荐

  1. java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

    http://langgufu.iteye.com/blog/2107023 java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果 ...

  2. 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码. file ...

  3. NIO详解(七):进程间通信(MappedByteBuffer)

    1. 前言 最近在研究Java进程间通信,为了了解Java中的SharedMemory共享内存.我特地去研究了一些Java NIO进程间通信的方式. 2. Java NIO MappedByteBuf ...

  4. 攻破JAVA NIO技术壁垒

    原文出处: 朱小厮 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty.学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能. ...

  5. java大文件读写操作

    转载自:http://blog.csdn.net/akon_vm/article/details/7429245 RandomAccessFile RandomAccessFile是用来访问那些保存数 ...

  6. java高效写文件_java如何高效读写10G以上大文件

    有一份10G以上大文本文件,需要替换里面的一些文本信息(每一行都有),如何高效读并替换掉生成新的文件 先分割成多个文件 多个线程操作多个文件,避免两个线程操作同一个文件 按行读文件并按行写入新的文件 ...

  7. Android高手笔记 - IO优化

    IO 优化不就是不在主线程读写大文件吗,真的只有这么简单吗? IO 基础 IO流程:应用程序 发送逻辑IO命令给文件系统,文件系统发送物理IO命令给存储设备/磁盘 文件系统 文件读(read)过程:应 ...

  8. 2022年RocketMQ面试题及答案

    1..消息队列有哪些使用场景 异步 解耦 流量削峰 2.为什么使用rocketMQ 性能: TPS 10000没问题 顺序消费: 可以保证一个队列里面的消息顺序消费,比如同一个订单的消息可以放到同一个 ...

  9. 详细讲解:RocketMQ的限时订单实战与RocketMQ的源码分析!

    目录 一.限时订单实战 1.1.什么是限时订单 1.2.如何实现限时订单 1.2.1.限时订单的流程 1.2.2.限时订单实现的关键 1.2.3.轮询数据库? 1.2.4.Java 本身的提供的解决方 ...

最新文章

  1. c库的rand/random随机数产生函数性能差?
  2. 推荐系统的作用和问题
  3. mysql 5.7.20主从配置_mysql-5.7.20源码安装 + 多实例 + 主从复制
  4. 如何去找一些还没有完全上市的 在私募投资的公司 D轮左右 财经媒体
  5. 一个mapper接口有多个mapper.xml 文件_爱了!分享一个基于Spring Boot的API、RESTful API项目种子(骨架)!...
  6. (JAVA)CollectionDemo2
  7. python-聚类图像分割
  8. sql server权限_保护SQL Server审核的访问权限
  9. linux内核奇遇记之md源代码解读之四
  10. 设计模式之十三:适配器模式(Adapter)
  11. Hadoop 入门教程(超详细)
  12. win7设置自动开机时间_电脑如何设置定时开机?瞬间让你的电脑启动变得随心所欲...
  13. linux ps1详解,Linux-玩转系统提示符PS1
  14. 天猫精灵 python_天猫精灵控制esp8266点led灯
  15. [[城市]普及]支付网关,什么是支付网关,第三方支付模式
  16. Python selenium实现全自动购买火车票
  17. Matlab rand()函数用法
  18. C++标准库之IO库
  19. prometheus启动报错Unit prometheus.service entered failed state.
  20. Python编程:从入门到实践第六章读书笔记6.3遍历字典

热门文章

  1. 四十一、Vue项目上手 | 用户管理系统 实现用户修改和删除功能(完成篇)
  2. 物体检测轻松上手:精度与速度实现兼得
  3. 阿里巴巴淘系开源大型3D家具数据集(3D-FUTURE)推动3D家居智能研究
  4. 智源-知乎联合发布大规模用户关系数据集,同步开启10万元竞赛
  5. 开课吧 Python专家级编程:机制与实操
  6. HDU1407 测试你是否和LTC水平一样高 暴力、二分、hash
  7. 多模态理论张德禄_结构动力学中的模态分析(3) —— 模态参数及实验模态分析...
  8. linux获得蓝牙外设mac,iOS获取蓝牙外设Mac地址
  9. 云服务器Linux jdk安装详解(centos8)
  10. 前后端分离报错The Token’s Signature resulted invalid when verified using the Algorithm: HmacSHA256