jdk中的MappedByteBuffer非常类似linux中的mmap将文件映射到虚拟内存,这样可以利用操作系统自带的虚拟内存实现来 提高io效率, 很多文档中提到这一点, 具体大家可以自行测试。 MappedByteBuffer有3种映射模式: MapMode.READ_ONLY:只读映射 MapMode.READ_WR

jdk中的MappedByteBuffer非常类似linux中的mmap将文件映射到虚拟内存,这样可以利用操作系统自带的虚拟内存实现来

提高io效率, 很多文档中提到这一点,具体大家可以自行测试。

MappedByteBuffer有3种映射模式:

MapMode.READ_ONLY:只读映射

MapMode.READ_WRITE?:读写映射

MapMode.PRIVATE?:copy on write映射,一旦需要改变原有buffer,拷贝一份原来的

本文通过一种测试代码来理解MappedByteBuffer使用MapMode.READ_WRITE以及MapMode.PRIVATE,特别是MAP_MODE.PRIVATE模式?

public class MMapTest {

private static FileChannel channel;

@BeforeClass

public static void runBeforeClass() throws FileNotFoundException {

String path = MMapTest.class.getResource("/test.txt").getPath();

File file = new File(path);

channel = new RandomAccessFile(file, "rw").getChannel();

}

@AfterClass

public static void runAfterClass() throws IOException {

channel.close();

}

@Before

public void runBeforeEveryTest() throws IOException {

ByteBuffer temp = ByteBuffer.allocate(100);

temp.put("12345".getBytes());

temp.flip();

channel.truncate(5);

channel.write(temp);

}

/**

*

* @author weip.pengw

* @time 2012-3-19 下午02:53:21

* @param buffer

* @throws Exception

*/

public static String dumpBuffer(ByteBuffer buffer) throws Exception {

StringBuffer sb = new StringBuffer();

int nulls = 0;

int limit = buffer.limit();

for (int i = 0; i < limit; i++) {

char c = (char) buffer.get(i);

if (c == '\u0000') {

nulls++;

continue;

}

if (nulls != 0) {

sb.append("|[" + nulls + " nulls]|");

nulls = 0;

}

sb.append(c);

}

return sb.toString();

}

/**

*

* @author weip.pengw

* @throws Exception

* @time 2012-3-19 下午02:45:28

*/

@Test

public void testCopyOnWrite() throws Exception {

// 产生一个文件,文件跨内存页

ByteBuffer temp = ByteBuffer.allocate(100);

temp.put("This is the file content".getBytes());

temp.flip();

channel.write(temp, 0);

temp.clear();

temp.put("This is more file content".getBytes());

temp.flip();

channel.write(temp, 8192);

// 产生两个MAPFILE

MappedByteBuffer rw = channel.map(FileChannel.MapMode.READ_WRITE, 0,

channel.size());

MappedByteBuffer cow = channel.map(FileChannel.MapMode.PRIVATE, 0,

channel.size());

// 测试之前

assertThat(

dumpBuffer(rw),

is("This is the file content|[8168 nulls]|This is more file content"));

assertThat(

dumpBuffer(cow),

is("This is the file content|[8168 nulls]|This is more file content"));

// 测试step1,修改rw前几个字节

rw.position(0);

rw.put("RW".getBytes());

rw.force();

assertThat(

dumpBuffer(rw),

is("RWis is the file content|[8168 nulls]|This is more file content"));

assertThat(

dumpBuffer(cow),

is("RWis is the file content|[8168 nulls]|This is more file content"));

// 测试step2,修改cow前几个字节,触发copy on write

cow.position(0);

cow.put("COW".getBytes());

assertThat(

dumpBuffer(rw),

is("RWis is the file content|[8168 nulls]|This is more file content"));

assertThat(

dumpBuffer(cow),

is("COWs is the file content|[8168 nulls]|This is more file content"));

// 测试step3,修改rw的最后几个字节,cow后面的字节反应了改变

rw.position(8192);

rw.put("RW".getBytes());

rw.force();

assertThat(

dumpBuffer(rw),

is("RWis is the file content|[8168 nulls]|RWis is more file content"));

assertThat(

dumpBuffer(cow),

is("COWs is the file content|[8168 nulls]|RWis is more file content"));

// 测试step4,修改cow的最后几个字节,再次触发copy on write

cow.position(8192);

cow.put("COW".getBytes());

assertThat(

dumpBuffer(rw),

is("RWis is the file content|[8168 nulls]|RWis is more file content"));

assertThat(

dumpBuffer(cow),

is("COWs is the file content|[8168 nulls]|COWs is more file content"));

// 测试step5,再次修改rw的前后几个字节,对cow没有了影响

rw.position(0);

rw.put("RW2".getBytes());

rw.position(8192);

rw.put("RW2".getBytes());

rw.force();

assertThat(

dumpBuffer(rw),

is("RW2s is the file content|[8168 nulls]|RW2s is more file content"));

assertThat(

dumpBuffer(cow),

is("COWs is the file content|[8168 nulls]|COWs is more file content"));

// cleanup

// channel.close();

}

重点看看代码中的测试方法testCopyOnWrite

1)产生一个较大空洞文件(本文操过8k),使得操作系统(代码在ubuntu10.04测试通过)无法在一页能映射该文件(跨内存页),这样才会有测试效果

2)将文件映射到两个MappedByteBuffer实例,一个是MapMode.READ_WRITE模式简称rw,一个是FileChannel.MapMode.PRIVATE模式简称cow

3) 测试之前,两个buff实例内容一致

4)第1步测试修改rw实例,由于没有触发copy on write,所以两个buff实例内容一致

5) 第2步测试修改cow实例的前几个字节,cow的修改只影响它本身,因为它修改的时候实际上重新拷贝了一份

6)第3步测试修改rw实例的后几个字节,居然在cow实例中能看到,之前不是说cow拷贝了一份吗?原因后面说

7)第4步测试修改cow实例的后几个字节,?cow的修改只影响它本身

8)第5步测试修改rw实例的前后字节,发现都没反映在cow实例中,的确和6)有所不同。

这说明:一开始没有修改cow,会共用rw的内存,

当cow修改了前几个字节,cow会拷贝内存,但明显cow实例是按内存页拷贝的,由于文件较长,?所以只拷贝了前一个部分,前面的是自己的,后面是共享的

?当cow修改了后几个字节?,cow才拷贝后面的内存页,这样的话,bw对文件后面的修改,cow也就看不到了

mmap java实现_理解java中的mmap相关推荐

  1. java 线程_理解java多线程

    树枝头玩魔法班卓琴弦乐器的生物与发光的蝴蝶,数字艺术风格,插画绘画creature with java多线程 1.实现Runnable接口相比于继承Thread类: (1)适合多个相同的程序代码的线程 ...

  2. Java 位运算理解 Java中的位移运算整理 Java右移n位 Java左移n位

    Java 位运算理解 Java中的位移运算整理 Java右移n位 Java左移n位 一.概述 1.在浏览一篇文章时,看到一个介绍 ,使用位移操作替代乘除法 ,若位移多位该怎么计算呢?  二.代码理解 ...

  3. java中字符流 字节流_理解Java中字符流与字节流的区别

    1. 什么是流 Java中的流是对字节序列的抽象,我们可以想象有一个水管,只不过现在流动在水管中的不再是水,而是字节序列.和水流一样,Java中的流也具有一个"流动的方向",通常可 ...

  4. java的弱引用_理解Java中的弱引用(Weak Reference)

    本篇文章尝试从What.Why.How这三个角度来探索Java中的弱引用,理解Java中弱引用的定义.基本使用场景和使用方法.由于个人水平有限,叙述中难免存在不准确或是不清晰的地方,希望大家可以指出, ...

  5. java中异常回收_理解Java垃圾回收

    当程序创建对象.数组等引用类型的实体时,系统会在堆内存中为这一对象分配一块内存,对象就保存在这块内存中,当这块内存不再被任何引用变量引用时,这块内存就变成垃圾,等待垃圾回收机制进行回收.垃圾回收机制具 ...

  6. java异常_聊聊Java中的异常及处理

    前言 在编程中异常报错是不可避免的.特别是在学习某个语言初期,看到异常报错就抓耳挠腮,常常开玩笑说编程1分钟,改bug1小时.今天就让我们来看看什么是异常和怎么合理的处理异常吧! 异常与error介绍 ...

  7. 为啥JAVA虚拟机不开发系统_理解Java虚拟机体系结构

    1 概述 众所周知,Java支持平台无关性.安全性和网络移动性.而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统一的编程接口,而不管下层操作系统是什么.正是得益于Jav ...

  8. java 对象压缩_理解Java对象:要从内存布局及底层机制说起,话说....

    前言 大家好,又见面了,今天是JVM专题的第二篇文章,在上一篇文章中我们说了Java的类和对象在JVM中的存储方式,并使用HSDB进行佐证,没有看过上一篇文章的小伙伴可以点这里:< 这篇文章主要 ...

  9. 【java】深入理解Java JVM虚拟机中init和clinit的区别

    1.概述 转载并且补充:深入理解Java JVM虚拟机中init和clinit的区别 原创 之所以来转载一下,是因为,有个学弟问了这个问题 这个知识点,回顾起来应该是我看 深入理解Java JVM虚拟 ...

最新文章

  1. 最小二乘法和最大似然估计
  2. 【Android 逆向】x86 CPU 架构体系 ( 堆内存 | 栈内存 | 函数调用 )
  3. MySQL最后一次查询耗时查询
  4. boost::gil模块实现cmyka转rgba的测试程序
  5. 一个很好地List实现源码
  6. .net 怎么在控制器action中返回一个试图_一个view事件分发,面试官6连问直击灵魂,我被虐的体无完肤...
  7. 了解.NET中的垃圾回收
  8. prim最小生成树算法 邻接表+STL实现
  9. 洛谷1966 火柴排队
  10. 利用前中,后中建立二叉搜索树和二叉树的镜像翻转
  11. 数据结构_郝斌老师自学大纲
  12. 古风系统仙侠文推荐_5本古典仙侠全本精品小说,文笔精湛,仙味十足,值得细品一二...
  13. 安卓apkcpu占用过高_Android CPU占用高问题分析
  14. 30天自制操作系统(day10)
  15. css3 如何画太极 和 奥运五环
  16. 去中心化云存储的前世今生 | 存储技术分享活动回顾
  17. 利用AutoSSH实现远程管理内网服务器
  18. ElasticSearch(全文检索服务的安装和使用)
  19. jvm内存管理-垃圾收集
  20. 计算机的硬盘维修,四大电脑硬盘常见错误及修复方案

热门文章

  1. linux系统下查看文件大小命令(以G/M/K为单位查看)
  2. 学习大学生安全教育的必要性不包括
  3. packetix ***连不上问题解决方法
  4. 从原理到操作,让你在 APISIX 中代理 Dubbo 服务更便捷
  5. Java迷宫版 吃豆人(有音乐)
  6. 家用台式计算机硬件配置清单,最新最全台式电脑配置清单2000-5000配置清单
  7. Java实现拼图小游戏(7)—— 作弊码和判断胜利
  8. udp协议没有粘包问题、基于socketserver实现并发的socket(基于tcp、udp协议)、基于udp协议的套接字、操作系统原理以及进程知识
  9. (附源码)springboot旅游公司网站设计 毕业设计110929
  10. 在RGUI中更新R 的版本