磁盘的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内存映射的更多相关文章

  1. Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer

    Atitit.病毒木马的快速扩散机制原理nio 内存映射MappedByteBuffer 1. Java NIO(New Input/Output)1 1.1. 变更通知(因为每个事件都需要一个监听者 ...

  2. Java NIO内存映射---上G大文件处理(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果 ...

  3. Java NIO 内存映射文件

    Java NIO 内存映射文件 @author ixenos 文件操作的四大方法 前提:内存的访问速度比磁盘高几个数量级,但是基本的IO操作是直接调用native方法获得驱动和磁盘交互的,IO速度限制 ...

  4. JAVA NIO 内存映射(转载)

    原文地址:http://blog.csdn.net/fcbayernmunchen/article/details/8635427     Java类库中的NIO包相对于IO 包来说有一个新功能是内存 ...

  5. (转)NIO 内存映射文件

    内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多. 内存映射文件 I/O 是通过使文件中的数据神奇般地出现为内存数组的内容来完成的.这其初听起来似乎 ...

  6. JAVA NIO FileChannel 内存映射文件

      文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...

  7. Java NIO之内存映射文件——MappedByteBuffer

    大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...

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

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

  9. NIO之通道(Channel)的原理与获取以及数据传输与内存映射文件

    通道(Channel) 由java.nio.channels包定义的,Channel表示IO源与目标打开的连接,Channel类似于传统的“流”,只不过Channel本身不能直接访问数据,Channe ...

随机推荐

  1. net+Oracle开发过程中遇到的小问题

    最新的项目开始使用Oracle后,5个月之间遇到一些在SqlServer中没有遇到的问题,这里记录并贴上一些常用的解决办法. Oracle相关 一.数据库不同版本还原: 刚开始我们一直使用Oracle ...

  2. ICMP TYPE-CODE查阅表

    我们在使用ICMP协议进行作业时,经常会用到ICMP类型和code,这里给出ICMP类型和code对应表. ICMP TYPE CODE对照表 TYPE CODE Description Query ...

  3. 部署Asp.net Core 项目发生502.5 或者500 没有其他提示信息

    最近将公司原来.NetCore 1.6的项目升级到.net Core 2.0首先发生 502.5的错误,包括IIS日志,Windows应用程序日志都没有记录问题始终解决不了,首先看看官网给出的解决方案 ...

  4. phpstudy 虚拟主机域名配置注意问题

    第一步:hosts文件中添加对应:127.0.0.1+空格+你的域名 第二部:在D:\phpStudy \Apache\conf\vhosts.conf中禁用470行 第三部:配置域名和引入程序地址

  5. 邓_html_选项卡

    ================================================= ================[  选项卡  ]================= ======= ...

  6. 版本控制——TortoiseSVN (1)安装与配置

    =================================版权声明================================= 版权声明:原创文章 禁止转载  请通过右侧公告中的“联系邮 ...

  7. Vuejs技术栈知识点小结

    前言 上家公司的项目主要是使用jQuery和Angular1,然后自己学了React,没想到来到这家公司突然开始做vue,不过vue还是挺容易上手的.下面是vue技术栈的一些总结,都是来自官网,主要是 ...

  8. Mysql 范围查询优化

    Range查询:用单独的Index的一个或多个index值来检索表的子集行数据,当然包含多个index. 1:一个index (单一部分)的range access 方法:(eg : 指的这种key ...

  9. IDEA翻译插件推荐Translation 安装和使用以及快捷键绑定

    首先第一步是安装该插件 如图: File -> setting -->plugins 进入该页面,点击如图所示按钮. 然后搜索 Translation 如图: 我们需要的结果一般都不会排在 ...

  10. python_如何实现可迭代对象和迭代器对象?

    什么是可迭代对象? 列表.字符串 for循环的本质? for循环要确保in后面的对象为可迭代对象,如何确保? iter() 方法得到一个迭代器对象 不停.__next__() 方法对迭代器对象进行迭代 ...