1、MappedByteBuffer是DirectByteBuffer的子類
2、MappedByteBuffer使用的是mmap技術。MappedByteBuffer將文件映射為內存,也可能會被存儲在虛擬內存里面,訪問的時候通過缺頁機制調進內存。
3、mmap可以實現兩個進程之間共享數據 http://kenby.iteye.com/blog/1164700
4、mmap原理 http://blog.chinaunix.net/uid-26669729-id-3077015.html
5、MappedByteBuffer有一個文件釋放問題,文件是在full gc的時候才會關閉 http://langgufu.iteye.com/blog/2107023
6、MappedByteBuffer能優化隨機讀(因為實際上會在內存里存放大量的頁/塊)

metaq在文件讀寫操作上做了一定的優化,使用內存映射的方式完成讀寫,替代了傳統的IO操作,從而大大的減少了文件讀寫系統調用的次數,提升了IO的性能。
傳統的文件訪問:
- 系統調用打開文件,獲取文件描述符
- 使用read write 系統調用進行IO
- 系統調用關閉文件
這種方式是非常低效的, 每一次I/O操作都需要一次系統調用。 另外, 如果若干個進程訪問同一個文件, 每個進程都要在自己的地址空間維護一個副本, 浪費了內存空間
內存映射的方式:
- 打開文件,得到文件描述符。
- 獲取文件大小
- 把文件映射成虛擬內存(mmap)
- 通過對內存的讀寫來實現對文件的讀寫(memset或memcpy)
- 卸載映射
- 關閉文件
首先建立好虛擬內存和磁盤文件之間的映射(mmap系統調用),當進程訪問頁面時產生一個缺頁中斷,內核將頁面讀入內存(也就是說把磁盤上的文件拷貝到內存中),並且更新頁表指向該頁面。
所有進程共享同一物理內存,物理內存中可以只存儲一份數據,不同的進程只需要把自己的虛擬內存映射過去就可以了,這種方式非常方便於同一副本的共享,節省內存。
經過內存映射之后,文件內的數據就可以用內存讀/寫指令來訪問,而不是用Read和Write這樣的I/O系統函數,從而提高了文件存取速度。
package com.ydd.study.hello.mmap; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; /** * 內存映射文件 * @author yunzhu.ydd * */ public class MapedFile { private final String FILE_NAME = "D://mapedFile.txt"; private final long fileSize = 1024 * 1024;// 1M private FileChannel fileChannel; private MappedByteBuffer mappedByteBuffer; private File file; public MapedFile() throws IOException { this.file = new File(FILE_NAME); this.fileChannel = new RandomAccessFile(this.FILE_NAME, "rw") .getChannel(); //產生一定大小的文件,byte默認都為0。也就是說文件的byte都被初始化為0了 this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0, fileSize); } /** * 寫 * @param str */ public void write(String str) { mappedByteBuffer.put(str.getBytes()); } /** * 讀文件 */ public void getAll() { System.out.println("capacity:"+mappedByteBuffer.capacity()); for(int i=0;i<mappedByteBuffer.capacity();i++) { char c=(char)mappedByteBuffer.get(i); if(c!=' '&&c!=0) System.out.print(c); } System.out.println(); } /** * 通過MappedByteBuffer操作文件 * @throws IOException */ public void test_寫和讀() throws IOException { System.out.println("capacity:"+mappedByteBuffer.capacity()); write("hello world"); getAll(); fileChannel.close(); } /** * MappedByteBuffer.slice()生成的是DirectByteBuffer,對該buffer寫操作會被直接寫到文件里面 * @param str * @throws IOException */ public void test_slic_寫和讀(String str) throws IOException { ByteBuffer buffer=mappedByteBuffer.slice(); buffer.put(str.getBytes()); System.out.println("mappedByteBuffer.clice產生的buffer類型為:"+buffer.getClass()); getAll(); fileChannel.close(); } public static void main(String[]a) throws IOException { MapedFile mappedFile=new MapedFile(); //mappedFile. test_寫和讀(); mappedFile.test_slic_寫和讀("hahahahahah"); } }
