数据开发_Java中内存映射文件

内存映射文件

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.
原文地址:https://www.cnblogs.com/ytwang/p/14031366.html