Java NIO 核心知识.下

[NIO 零拷贝](#NIO 零拷贝)

零拷贝是提升 IO 操作性能的一个常用手段,像 ActiveMQ、Kafka 、RocketMQ、QMQ、Netty 等顶级开源项目都用到了零拷贝。

零拷贝是指计算机执行 IO 操作时,CPU 不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及 CPU 的拷贝时间。也就是说,零拷贝主要解决操作系统在处理 I/O 操作时频繁复制数据的问题。零拷贝的常见实现技术有: mmap+writesendfilesendfile + DMA gather copy

下图展示了各种零拷贝技术的对比图:

可以看出,无论是传统的 I/O 方式,还是引入了零拷贝之后,2 次 DMA(Direct Memory Access) 拷贝是都少不了的。因为两次 DMA 都是依赖硬件完成的。零拷贝主要是减少了 CPU 拷贝及上下文的切换。

Java 对零拷贝的支持:

  • MappedByteBuffer 是 NIO 基于内存映射(mmap)这种零拷⻉⽅式的提供的⼀种实现,底层实际是调用了 Linux 内核的 mmap 系统调用。它可以将一个文件或者文件的一部分映射到内存中,形成一个虚拟内存文件,这样就可以直接操作内存中的数据,而不需要通过系统调用来读写文件。
  • FileChanneltransferTo()/transferFrom()是 NIO 基于发送文件(sendfile)这种零拷贝方式的提供的一种实现,底层实际是调用了 Linux 内核的 sendfile系统调用。它可以直接将文件数据从磁盘发送到网络,而不需要经过用户空间的缓冲区。关于FileChannel的用法可以看看这篇文章:Java NIO 文件通道 FileChannel 用法

代码示例:

private void loadFileIntoMemory(File xmlFile) throws IOException {

FileInputStream fis = new FileInputStream(xmlFile);

// 创建 FileChannel 对象

FileChannel fc = fis.getChannel();

// FileChannel.map() 将文件映射到直接内存并返回 MappedByteBuffer 对象

MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());

xmlFileBuffer = new byte(int)fc.size();

mmb.get(xmlFileBuffer);

fis.close();

}

总结

这篇文章我们主要介绍了 NIO 的核心知识点,包括 NIO 的核心组件和零拷贝。

如果我们需要使用 NIO 构建网络程序的话,不建议直接使用原生 NIO,编程复杂且功能性太弱,推荐使用一些成熟的基于 NIO 的网络编程框架比如 Netty。Netty 在 NIO 的基础上进行了一些优化和扩展比如支持多种协议、支持 SSL/TLS 等等。

相关推荐
吃饱了得干活13 小时前
Spring Cloud Gateway 微服务网关:路由、断言、过滤器
java·spring cloud
lwx5728015 小时前
探秘InnoDB:搞懂它的内存、线程、磁盘与日志刷盘策略
java·后端
Flynt16 小时前
从Spring Boot 4.0升到4.1,我在Maven和gRPC上栽了跟头
java·spring boot·后端
plainGeekDev17 小时前
Activity 间传值 → Navigation 参数
android·java·kotlin
plainGeekDev17 小时前
onActivityResult → ActivityResult API
android·java·kotlin
Sunia17 小时前
《AgentX 专栏》10-生产部署:3台2C4G云服务器把企业级Agent真正跑起来的完整方案
java·架构
ZhengEnCi18 小时前
J7A-高级Java工程师面试三道灵魂拷问-深度广度与工程素养的终极检验
java·后端
狼爷2 天前
吃透 Java Function 接口,搞定 99% 的 Stream 场景
java·函数式编程
祎雪双十Gy2 天前
从 DataX 的配置加载说起:我用 FastJson2 做了一个轻量级动态配置管理库
java·后端
小锋java12342 天前
分享一套锋哥原创的SpringBoot4+Vue3宠物领养网站系统
java