目录
- 1- 引言:直接内存概述
- 1-1 直接内存是什么?直接内存的定义(What)
- 1-2 为什么用直接内存?Java程序对直接内存的使用 (Why)
 
- 2- ⭐核心:详解直接内存(How)
- 2-1 文件拷贝案例介绍对比常规 IO(BIO) 和 NIO
- 常规 IO 的操作流程
- NIO 的操作流程
 
 
- 3- 小结:
- 3-1 什么是直接内存?
 
1- 引言:直接内存概述
1-1 直接内存是什么?直接内存的定义(What)
- 直接内存:并不属于 JVM 中的内存结构,不由 JVM 进行管理。是虚拟机的系统内存,常见于 NIO 操作时,用于数据缓冲区,它分配回收成本较高,但读写性能高。
1-2 为什么用直接内存?Java程序对直接内存的使用 (Why)
- 高性能需求:直接内存的读写性能高于传统的JVM堆内存,因为减少了内存复制的次数。在进行大量数据的读写操作时,使用直接内存可以显著提高性能。
- NIO操作:Java NIO(Non-blocking IO)库通过使用直接内存来提升IO操作的吞吐量。直接内存允许Java程序直接访问操作系统的内存,从而减少了数据在系统缓冲区和Java堆缓冲区之间复制的开销。
- 资源共享:直接内存是操作系统内存的一部分,可以被操作系统和Java程序共享访问,这使得数据处理更加高效。
- 避免垃圾回收:直接内存不受JVM的垃圾回收机制影响,减少了由于垃圾回收导致的性能波动,对一些高性能应用场景尤为重要。
2- ⭐核心:详解直接内存(How)
2-1 文件拷贝案例介绍对比常规 IO(BIO) 和 NIO
- Java 代码完成文件拷贝
- 场景:E:/bak1下有文件 需要拷贝到 ——>E:/bak2文件夹下

package com.heima.jvm;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class DirectMemoryDemo {
    static final String FROM = "E:\\bak1\\01-java成神之路.mp4";
    static final String TO = "E:\\bak2\\abc.mp4";
    static final int _1Mb = 1024 * 1024;
    public static void main(String[] args) {
        io(); // 256.8563
        directBuffer(); // 63.2449
    }
    private static void directBuffer() {
        long start = System.nanoTime();
        try (FileChannel from = new FileInputStream(FROM).getChannel();
             FileChannel to = new FileOutputStream(TO).getChannel()) {
            ByteBuffer bb = ByteBuffer.allocateDirect(_1Mb);
            while (true) {
                int len = from.read(bb);
                if (len == -1) break;
                bb.flip();
                to.write(bb);
                bb.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("NIO Time: " + (end - start) / 1e6 + " ms");
    }
    private static void io() {
        long start = System.nanoTime();
        try (FileInputStream fis = new FileInputStream(FROM);
             FileOutputStream fos = new FileOutputStream(TO)) {
            byte[] buffer = new byte[_1Mb];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        long end = System.nanoTime();
        System.out.println("IO Time: " + (end - start) / 1e6 + " ms");
    }
}

- 结果分析:NIO 比 BIO 效率更高
常规 IO 的操作流程
- Java本身不具备磁盘读写的能力,如果 Java 需要对磁盘进行读写,必须调用操作系统提供的函数(Native 修饰的本地方法)
①内存操作 ——> CPU状态切换
- Java程序运行在用户态(User Space),当需要进行磁盘读写操作时,必须切换到内核态(Kernel Space)。这种切换会消耗CPU资源。
②内存操作 ——> 数据读取和缓冲区使用:
- 通过调用操作系统的函数,将磁盘文件读取到系统缓存区中。
- 为了避免内存占用过大,操作系统利用缓冲区分批次读取数据。
③系统缓冲区与Java缓冲区的交互:
- 系统的缓冲区中 Java 代码无法直接运行,因此 Java 程序需要在堆内存中分配一块缓冲区(Java缓冲区)来存储数据,通常通过new byte[]的方式分配。
⑤数据复制:
- 数据从系统缓冲区复制到Java缓冲区。
- Java代码通过读取Java缓冲区中的数据进行操作。
- 由于存在两块缓冲区,数据需要在两块内存中存储两次,这会导致不必要的复制操作,从而降低效率。
问题所在:多次数据复制
- 因为数据需要从系统缓冲区复制到Java缓冲区,导致了数据的重复存储。
- 这种多次数据复制不仅消耗内存资源,还会影响整体性能。

NIO 的操作流程

- 在 NIO 的过程中,操作系统直接在内存中划分出了一个 直接内存 缓冲区, Java 代码也可以直接在直接访问直接内存。
- 直接内存对于操作系统和 Java 来说都是可以共享的区域,这就是直接内存。这就是直接内存带来的好处,直接提高了文件的 IO 操作。
3- 小结:
3-1 什么是直接内存?

![C++ - char*、const char*、char[]、string](https://i-blog.csdnimg.cn/direct/001314dcd96147169e9554542c286abe.png)

![[Vulnhub] Raven2 PHPMailer-RCE+MSQP:Mysql权限提升](https://img-blog.csdnimg.cn/img_convert/58ce9dd1b47cb57816af2d521b6076ec.jpeg)
















