直接内存or系统内存

直接内存(Direct Memory)并不是JVM运行时数据区的一部分,也不是Java虚拟机规范中定义的内存区域。
但是这部分内存也被频繁地使用,而且也可能导致OutOfMemoryError异常出现。
JDK 1.4中加入了NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的IO方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。
这样能在一些场景中显著提高性能,因为避免了在Java堆和Native堆中来回复制数据。
NIO数据读写时,缓冲区内存使用的是(直接内存\系统内存)
NIO中的ByteBuffer使用的是直接内存

直接内存:
分配回收成本高,读写性能高
不受JVM内存回收管理,手动分配和释放
static final String FROM = "E:\\BaiduNetdiskDownload\\xxxx.pdf";
static final String TO = "E:\\BaiduNetdiskDownload\\c.x";
static final int _1MB = 1024 * 1024;

public static void main(String[] args) {
    io();
    fn();
}
// nio(更快)
private static void fn() {
    long start = System.nanoTime();
    try(FileChannel from  = new FileInputStream(FROM).getChannel();
        FileChannel to = new FileOutputStream(TO).getChannel()){

        ByteBuffer bb = ByteBuffer.allocateDirect(_1MB);
        int len;
        while((len = from.read(bb)) != -1){
            bb.flip();
            to.write(bb);
            bb.clear();
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
    long end = System.nanoTime();
    System.out.println("timeSpent: " + (end - start) / 1000_000.0);
}
private static void io() {
    long start = System.nanoTime();
    try(FileInputStream from  = new FileInputStream(FROM);
        FileOutputStream to = new FileOutputStream(TO)){

        byte[] bytes = new byte[_1MB];
        int len;
        while((len = from.read(bytes)) != -1){
            to.write(bytes,0,len);
        }

    } catch (IOException e) {
        e.printStackTrace();
    }
    long end = System.nanoTime();
    System.out.println("timeSpent: " + (end - start) / 1000_000.0);
}

allocateDirect方法
底层使用unsafe对象进行分配,回收内存
Cleaner虚引用来监测ByteBuffer对象,一旦ByteBuffer对象被垃圾回收,ReferenceHandler后台线程
就会调用Cleanner的clean方法来释放内存
clean方法中调用一个Runnable对象的run方法来调unsafe的freeMemory方法释放内存

你可能感兴趣的:(JVM,jvm,java)