NIO内存映射
磁盘的IO因为速度较慢,可能成为系统运行的瓶颈。所以磁盘的IO在操作系统级实现了提前读,延迟写的机制来提升IO的性能。
提前读就是一次读取需求的数据的同时多读接下来的一段数据至OS缓冲区中,延迟写就是待OS缓冲区中的数据到了一定量时一次写入。
Java中的Bufferxxx类也提供了缓冲区来完成提前读的功能,如果下一次需要读的数据已经在缓冲区了,就直接从缓冲区中取数据。
NIO的内存映射不在直接读文件到OS的缓冲区中,而是直接在JVM中为文件分配了一段内存区域,就像直接在内存中读取文件一样。速度较传统的IO要快很多,文件体积较小时速度差异不是很明显,但文件体积较大时速度的差异就会很明显。
package nio; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; public class MappedByteBufferTest { private static String sourceFileName = "UCS_PM_1.1.5_EN.sql";
private static String dstFileNameByMappedBuffer = "new.sql";
private static String dstFileNameByFileCopy = "new1.sql";
private static String dstFileNameByAllocateDirect = "new2.sql";
private static FileChannel readChannel, writeChannel;
private static long start;
private static long length; public static void main(String[] args) throws Exception {
mapBufferWriteFile(); //使用内存映射流来完成文件复制
testFileCopy(); //使用普通的IO流来完成文件复制
allocateDirectWriteFile(); //使用DirectMemory来完成文件复制
} public static void mapBufferWriteFile() {
try {
start = System.currentTimeMillis();
RandomAccessFile fos = new RandomAccessFile(dstFileNameByMappedBuffer, "rw");
writeChannel = fos.getChannel();
//writeChannel.position(writeChannel.size()); append to file end position RandomAccessFile fis = new RandomAccessFile(sourceFileName, "r");
readChannel = fis.getChannel();
length = readChannel.size();
MappedByteBuffer mbb = readChannel.map(FileChannel.MapMode.READ_ONLY, 0, length);
writeChannel.write(mbb);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
readChannel.close();
writeChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("mapBufferWriteFile:" + (System.currentTimeMillis() - start));
}
} private static void testFileCopy() {
start = System.currentTimeMillis();
BufferedInputStream bis =null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream(sourceFileName));
bos = new BufferedOutputStream(new FileOutputStream(dstFileNameByFileCopy));
byte[] bytes = new byte[1024];
int index = 0;
int b = bis.read();
while(b != -1){
bytes[index] = (byte) b;
index ++;
if(index == 1023){
bos.write(bytes, 0, index);
index = 0;
b = bis.read();
}else{
b = bis.read();
}
}
if(index != 1023){
bos.write(bytes, 0, index);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
try {
bis.close();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("testFileCopy:" + (System.currentTimeMillis() - start));
} private static void allocateDirectWriteFile() {
try {
start = System.currentTimeMillis();
RandomAccessFile fos = new RandomAccessFile(dstFileNameByAllocateDirect, "rw");
writeChannel = fos.getChannel(); RandomAccessFile fis = new RandomAccessFile(sourceFileName, "r");
readChannel = fis.getChannel();
length = readChannel.size();
ByteBuffer mbb = ByteBuffer.allocate((int)readChannel.size());
readChannel.read(mbb);
mbb.flip();
writeChannel.write(mbb);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
readChannel.close();
writeChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("allocateDirectWriteFile:" + (System.currentTimeMillis() - start));
}
}
}
NIO中提供了3种内存映射模式,即:只读(readonly)、读写(read_write)、专用(private) ,对于 只读模式来说,如果程序试图进行写操作,则会抛出ReadOnlyBufferException异常;第二种的读写模式表明了通过内存映射文件的方式写或修改文件内容的话是会立刻反映到磁盘文件中去的,别的进程如果共享了同一个映射文件,那么也会立即看到变化。
除了内存映射之外,还有一种快速读取文件的方式,叫做DirectMemory。DirectMemory也是将文件映射到内存中,只不过占用的不再是JVM的内存,而是非JVM的内存。
直接内存DirectMemory的大小默认为 -Xmx 的JVM堆的最大值,但是并不受其限制,而是由JVM参数 MaxDirectMemorySize单独控制。
DirectMemory所占用的内存无法手动的去释放,只能在 JVM执行 full gc 的时候才会被回收,那么如果在其上分配过大的内存空间,那么也将出现 OutofMemoryError。
如果系统中用到了DirectMemory,则一定要监控其使用的情况,否则很容易导致系统运行缓慢。
-Xms -Xmx不只局限于物理内存的大小,而是也综合虚拟内存的大小,JVM会根据电脑虚拟内存的设置来调节。
NIO内存映射的更多相关文章
- Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer
Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer 1. Java NIO(New Input/Output)1 1.1. 变更通知(因为每个事件都需要一个监听者 ...
- Java NIO内存映射---上G大文件处理(转)
林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果 ...
- Java NIO 内存映射文件
Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...
- JAVA NIO 内存映射(转载)
原文地址:http://blog.csdn.net/fcbayernmunchen/article/details/8635427 Java类库中的NIO包相对于IO 包来说有一个新功能是内存 ...
- (转)NIO 内存映射文件
内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多. 内存映射文件 I/O 是通过使文件中的数据神奇般地出现为内存数组的内容来完成的.这其初听起来似乎 ...
- JAVA NIO FileChannel 内存映射文件
文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...
- Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件
通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...
随机推荐
- 阻止浏览器冒泡事件,兼容firefox和ie
//得到事件 function getEvent(){ if(window.event) {return window.event;} func=getEvent.caller; while(func ...
- 96、python version 3.6 required,which was not fount in the registry(python3.6安装scrapy)
在安装scrapy时遇到问题 环境:win10(64位), Python3.6(64位) 安装scrapy: 1.安装wheel(安装后,便支持通过wheel文件安装软件) pip3 install ...
- Web Component总结
Web Component 一个Web组件通常由四个部分组成:模板.Shadow DOM.自定义元素与打包,其中Shadow DOM解决了组件在页面中的封装问题 Shadow DOM 有shadow ...
- Micropython TPYBoard 智能温控小风扇资料分享
南方都下大雪了,苦逼的北方还没下雪,天寒地冻,不过这几天办公室空调开太大了就想到做一个温控小风扇,简单模型出来了.等夏天一定做一个美观精致的小风扇送给女朋友(如果有的话QAQ)话不多说直接上干货.(跪 ...
- ios知识点总结——UITableView的展开与收缩及横向Table
UITableVIew是iOS开发中使用最为广泛的一种控件,对于UITableView的基本用法本文不做探讨,本文主要是针对UITableView的展开与收缩进行阐述,在文章的后面也会探讨一下横向ta ...
- JavaScript获取当前url根目录(路径)
jsp: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&q ...
- Java调用阿里云短信通道服务【千锋】
这里我们使用SpringBoot 来调用阿里通信的服务. 阿里通信,双11.收到短信,日发送达6亿条.保障力度非常高. 使用的步骤: 1.1. 第一步:需要开通账户 1.2. 第二步:阅读接口文档 1 ...
- FormsAuthentication.HashPasswordForStoringInConfigFile 的替代方法
由于项目中要和php对接,要将一段字符串生成md5(16位)验证码,在英文字符时,没有太大问题,但在遇到中文时,两边字条始终不一致. php是别人的项目,看不到源码,网上一查,估计是这样写的: < ...
- 记录一次tomcat下项目没有加载成功
哥们儿实在太low了,web.xml文件中加载的spring mybatis配置文件和配置的文件不是同一个文件名导致的!
- linkin大话数据结构--List
List:Collection子接口 List是有序的集合,集合中每个元素都有对应的顺序序列.List集合可使用重复元素,可以通过索引来访问指定位置的集合元素(顺序索引从0开始),List集合默认按元 ...