内存映射文件
1.FileChannel 和外界的介质进行交互
有3种模式:READ_ONLY(只读)、READ_WRITE(读写)、PRIVATE(私有,用于copy-on-write)
1.MappedByteBuffer一旦建立,就与创建它的通道无关,即通道关闭时,不影响该缓冲器
FileChannel channel = FileChannel.open(path,options);
2. MappedByteBuffer map
2.缓冲区的操作
缓冲区的操作可以查看Java API java.nio.Buffer
3.加锁
多个线程访问的情况下考虑
memory-map files
Java Memory-Mapped File所使用的内存分配在物理内存而不是JVM堆内存,且分配在OS内核
在一般的文件读写中,会有两次数据拷贝,一次是从硬盘拷贝到操作系统内核,另一次是从操作系统内核拷贝到用户态的应用程序。
而在内存映射文件中,一般情况下,只有一次拷贝,且内存分配在操作系统内核,应用程序访问的就是操作系统的内核内存空间。
Java语言通过java.nio包支持内存映射文件和IO
对于一般的文件读写不需要使用内存映射文件,
但如果处理的是大文件,要求极高的读写效率,
比如数据库系统或繁忙的电子交易系统,
或者需要在不同程序间进行共享和通信,那就可以考虑内存映射文件
读写内存映射文件是操作系统来负责的,因此,即使你的Java程序在写入内存后就挂掉了,只要操作系统工作正常,数据就会写入磁盘
Direct字节缓存比non-direct字节缓存性能要好
代码示例
import java.nio.ByteBuffer;
public class ByteBufferExp {
public static void main(String args[]) {
// 启动JAVA虚拟机时使用参数-Xmx100m
Runtime run = Runtime.getRuntime();
System.out.println("最大内存MB = " + run.maxMemory()/1024/1024);
System.out.println("已分配内存 = " + run.totalMemory()/1024/1024);
System.out.println("已分配内存中的剩余空间 = " + run.freeMemory()/1024/1024);
System.out.println("已分配内存中的使用空间 = " + (run.totalMemory() -run.freeMemory())/1024/1024 );
System.out.println("剩余最大可用于 内存 = " + (run.maxMemory()+ run.freeMemory()-run.totalMemory())/1024/1024);
System.out.println("----------allocate--------");
//4个静态工厂方法来获得ByteBuffer的实例
System.out.println("before alocate 即已分配内存中的剩余空间:" + run.freeMemory()/1024/1024);
// 从 堆空间 中分配一个容量大小为capacity的byte数组作为缓冲区的byte数据存储器
//将创建一个容量为 26字节的ByteBuffer,如果发现创建的缓冲区容量太小,唯一的选择就是重新创建一个大小合适的缓冲区.
ByteBuffer buffer = ByteBuffer.allocate(26*1024*1024);
// 缓冲区都有4个属性:capacity、limit、position
// capacity 容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
System.out.println("缓冲区 buffer = " + buffer);
System.out.println("缓冲区alocate 之后:" + run.freeMemory()/1024/1024);
//通过操作系统来创建内存块用作缓冲区 这部分直接用的系统内存,所以对JVM的内存没有影响
ByteBuffer directBuffer = ByteBuffer.allocateDirect(100*1024*1024);
System.out.println("直接缓冲区 directBuffer = " + directBuffer);
System.out.println(" 直接缓冲区 direct alocate 之后:" + run.freeMemory()/1024/1024);
System.out.println("----------Test wrap--------");
// 通过包装的方法创建的缓冲区保留了被包装数组内保存的数据
byte[] bytes = new byte[32];
buffer = ByteBuffer.wrap(bytes);
System.out.println("缓冲区wrap buffer = " + buffer);
System.out.println("wrap buffer 之后:" + run.freeMemory()/1024/1024);
// 以指定偏移量和长度,这个offset也就是包装后byteBuffer的position,
// 而length呢就是limit-position的大小,从而我们可以得到limit的位置为length+position(offset)
buffer = ByteBuffer.wrap(bytes, 10, 10);
System.out.println("缓冲区wrap buffer = " + buffer);
System.out.println("wrap buffer 之后:" + run.freeMemory()/1024/1024);
}
}
A byte buffer,一个字节缓冲区
Objects of this class may reside almost entirely in memory-map files.
That is the primary reason for them to be considered immutable, since no reallocation is possible when using2020/11/20 memory-mapped files.