传统io 流拷贝文件的原理
java 本身不具备磁盘读写能力 需要调用操作系统提供的函数 System 当切换系统函数时 CPU才会去磁盘读取文件,然后会在操作系统内存中画出一块 系统缓冲区 然后将文件内容分次读取到系统缓冲区,java 不能直接读取系统缓存区 ,所以java 会在堆内存中 分配出一个 java缓冲区,然后在间接的将系统缓存区的数据读取到java缓冲区,最后调用java的 写入操作,最终反复读写,到最后文件复制到目标地址
缺点 因为需要分配2个缓冲区 来造成不必要的复制 造成效率低下
使用NIO流
它会在 系统内存 之间 画出一个 缓冲区即直接内存 ,java可以访问到这个 直接内存,所以cpu会将文件 读取到这个直接内存 ,而java 也可以读取这个直接内存 进行文件复制,也就是比传统io流少了一次缓冲区文件复制操作 所以效果成倍提升了
如何分配直接内存
我们可以使用 jdk 自带的 Nio 包下的ByteBuffer 来操作
分配直接内存 和释放直接内存底层 调用的方法
unsafe里的 allocateMenory 方法 进行直接内存分配
unsafe里的 freeMemory方法 进行释放直接内存
ByteBuffer 分配内存和释放内存原理
我们来看下 这个ByteBuffter里的 allocateDirect方法
其调用了 DirectByteBuffer 构造器
我们可以看到 DirectByteBuffter 构造方法里 面调用 unsafe里的 allocateMenory 方法 进行直接内存分配
这里 this 是指当前对象 如果当前对象被回收 则触发 虚引用对象 Cleaner 对象里的 clean 方法 进而 直接调用 传入构造注入的 new Deallocator(这个Deallocator 实现了 Runnable接口) 里的run方法 这个run方法里面 会调用 unsafe里的 freeMemory方法 从而直接释放直接内存