【NIO】MappedByteBuffer-内存映射文件 I/O
操作系统会在负责执行映射,用于操作大文件
java io操作中通常采用BufferedReader,BufferedInputStream等带缓冲的IO类处理大文件;java nio中引入了一种基于MappedByteBuffer操作大文件的方式,其读写性能极高
FileChannel提供了map方法把文件映射到虚拟内存,通常情况可以映射整个文件,如果文件比较大,可以进行分段映射
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024); //fc-->FileChannel
//map通过native函数map0完成文件的映射工作,返回DirectByteBuffer
MappedByteBuffer的get方法最终通过DirectByteBuffer.get方法实现的
public byte get() {
return ((unsafe.getByte(ix(nextGetIndex()))));
}
public byte get(int i) {
return ((unsafe.getByte(ix(checkIndex(i)))));
}
private long ix(int i) {
return address + (i << 0);
}
map0()函数返回一个地址address,这样就无需调用read或write方法对文件进行读写,通过address就能够操作文件。底层采用unsafe.getByte方法,通过(address + 偏移量)获取指定内存的数据。
- 第一次访问address所指向的内存区域,导致缺页中断,中断响应函数会在交换区中查找相对应的页面,如果找不到(也就是该文件从来没有被读入内存的情况),则从硬盘上将文件指定页读取到物理内存中(非jvm堆内存)。
- 如果在拷贝数据时,发现物理内存不够用,则会通过虚拟内存机制(swap)将暂时不用的物理页面交换到硬盘的虚拟内存中
性能:
从代码层面上看,从硬盘上将文件读入内存,都要经过文件系统进行数据拷贝,并且数据拷贝操作是由文件系统和硬件驱动实现的,理论上来说,拷贝数据的效率是一样的。
但是通过内存映射的方法访问硬盘上的文件,效率要比read和write系统调用高,这是为什么?
- read()是系统调用,首先将文件从硬盘拷贝到内核空间的一个缓冲区,再将这些数据拷贝到用户空间,实际上进行了两次数据拷贝;
- map()也是系统调用,但没有进行数据拷贝,当缺页中断发生时,直接将文件从硬盘拷贝到用户空间,只进行了一次数据拷贝。
所以,采用内存映射的读写效率要比传统的read/write性能高
总结:
- MappedByteBuffer使用虚拟内存,因此分配(map)的内存大小不受JVM的-Xmx参数限制,但是也是有大小限制的。
- 如果当文件超出1.5G限制时,可以通过position参数重新map文件后面的内容。
- MappedByteBuffer在处理大文件时的确性能很高,但也存在一些问题,如内存占用、文件关闭不确定,被其打开的文件只有在垃圾回收的才会被关闭,而且这个时间点是不确定的。
javadoc中也提到:A mapped byte buffer and the file mapping that it represents remainvalid until the buffer itself is garbage-collected.*
【NIO】MappedByteBuffer-内存映射文件 I/O的更多相关文章
- Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...
- JAVA NIO FileChannel 内存映射文件
文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- Java NIO 内存映射文件
Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
- JAVA NIO之浅谈内存映射文件原理与DirectMemory
JAVA类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- 【NIO】NIO之浅谈内存映射文件原理与DirectMemory
Java类库中的NIO包相对于IO 包来说有一个新功能是内存映射文件,日常编程中并不是经常用到,但是在处理大文件时是比较理想的提高效率的手段.本文我主要想结合操作系统中(OS)相关方面的知识介绍一下原 ...
- (转)NIO 内存映射文件
内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多. 内存映射文件 I/O 是通过使文件中的数据神奇般地出现为内存数组的内容来完成的.这其初听起来似乎 ...
- 内存映射文件MappedByteBuffer和Buffer的Scattering与Gathering
上一篇讲到的DirectByteBuffer继承自MappedByteBuffer 一.MappedByteBuffer MappedByteBuffer的定义: A direct byte buff ...
- Java-NIO(五):通道(Channel)的数据传输与内存映射文件
通道(Channel)的数据传输(采用非直接缓冲区) @Test public void testChannel() throws IOException { FileInputStream file ...
随机推荐
- oracle查看数据库版本和字符集
以下以oralce为例, 查看数据库版本? 可以在pl/sql上执行:select * from v$version; 查看字符集? select * from v$nls_parameters; s ...
- 树莓派上安装boost库
一.安装boost库 sudo apt-get install libboost-dev aptitude search boost 二.编写测试代码 #include <iostream> ...
- Springboot项目静态资源配置
springboot项目的静态资源配置网上有好多,说的也很详细 我今天出错是自定义了一个filter,在shiro里配置的/**,自定义filter 所以一直报302
- Django中的HttpRequsest 和Httpresponse对象
HttpRequest对象:每一个用户请求在到达视图函数的同时,django会自动创建一个HttpRequest对象并把这个对象当做第一个参数传给要调用的views方法,HttpRequest对象里封 ...
- Ajax,ajax封装
/** * Created by liyinghao on 2016/8/23. */ /*仿jQuery中的ajax方法,简单版实现;封装ajax的工具函数*/ /* * 1 请求方式 type g ...
- JS检查断网
window.addEventListener('load', function() { function updateOnlineStatus(event) { var condition = na ...
- python:TypeError: main() takes 0 positional arguments but 1 was given
TypeError: main() takes 0 positional arguments but 1 was given def main(self): 括号里加上self就好了
- adb 常用命令大全
adb 常用命令大全 1. 显示系统中全部Android平台: android list targets 2. 显示系统中全部AVD(模拟器): android list avd ...
- 可重入锁:ReentrantLock理解使用
(一)可重入性 可重入性描述这样的一个问题:一个线程在持有一个锁的时候,它内部能否再次(多次)申请该锁.如果一个线程已经获得了锁,其内部还可以多次申请该锁成功.那么我们就称该锁为可重入锁.通过以下伪代 ...
- ollvm 使用——“Cannot open /dev/random”错误的解决方法
找到 \obfuscator-llvm-4.0\lib\Transforms\Obfuscation\CryptoUtils.cpp 这个文件, 新增两个头文件 #include <window ...