第一章Netty,NIO零拷贝详细实现代码 基于前文对 ‌NIO 零拷贝原理‌sendfile 与 mmap及‌高并发场景‌的讨论以下是两种核心零拷贝技术的详细 Java 实现代码。先看一段传统IO模型的文件拷贝代码packagecom.example.demo;importjava.io.File;importjava.io.IOException;importjava.io.RandomAccessFile;importjava.net.Socket;publicclassFileNioTest{publicstaticvoidmain(String[]args)throwsIOException{FilefnewFile(netty.txt);RandomAccessFilefilenewRandomAccessFile(f,r);byte[]bufnewbyte[(int)f.length()];intreadfile.read(buf);SocketsocketnewSocket();socket.getOutputStream().write(buf);}}传统IO工作流程一、 基于 transferTo 的文件网络传输推荐这是最纯粹的零拷贝适用于‌静态资源服务器‌或‌大文件上传/下载‌。数据直接在内核态从 Page Cache 传输到 Socket Buffer不经过用户态。1. 服务端代码发送文件importjava.io.FileInputStream;importjava.net.InetSocketAddress;importjava.nio.channels.FileChannel;importjava.nio.channels.ServerSocketChannel;importjava.nio.channels.SocketChannel;publicclassZeroCopyServer{publicstaticvoidmain(String[]args)throwsException{// 1. 创建 ServerSocketChannelServerSocketChannelserverSocketChannelServerSocketChannel.open();serverSocketChannel.bind(newInetSocketAddress(8080));System.out.println(Server started on port 8080...);while(true){// 2. 接受连接SocketChannelsocketChannelserverSocketChannel.accept();// 3. 获取文件通道FileChannelfileChannelnewFileInputStream(large_file.dat).getChannel();// 4. 【核心】零拷贝传输// transferTo 底层调用 sendfile数据不经过用户空间longtransferredfileChannel.transferTo(0,fileChannel.size(),socketChannel);System.out.println(Total bytes transferred: transferred);// 5. 关闭资源fileChannel.close();socketChannel.close();}}}2. 客户端代码接收文件importjava.io.FileOutputStream;importjava.net.InetSocketAddress;importjava.nio.channels.FileChannel;importjava.nio.channels.SocketChannel;publicclassZeroCopyClient{publicstaticvoidmain(String[]args)throwsException{// 1. 连接服务器SocketChannelsocketChannelSocketChannel.open();socketChannel.connect(newInetSocketAddress(localhost,8080));// 2. 获取文件输出通道FileChannelfileChannelnewFileOutputStream(received_file.dat).getChannel();// 3. 读取数据并写入文件// 注意客户端接收通常仍涉及一次从内核到用户空间的拷贝除非使用 DirectBuffer write// 但服务端发送已实现零拷贝整体性能显著提升longbytesReadfileChannel.transferFrom(socketChannel,0,Long.MAX_VALUE);System.out.println(Total bytes received: bytesRead);// 4. 关闭资源fileChannel.close();socketChannel.close();}}二、 基于 MappedByteBuffer 的大文件随机读写适用于‌数据库索引‌、‌日志分析‌等需要频繁随机访问大文件的场景。通过内存映射避免传统 read/write 的系统调用开销。1. 写入大文件示例importjava.io.RandomAccessFile;importjava.nio.MappedByteBuffer;importjava.nio.channels.FileChannel;publicclassMappedFileWriter{publicstaticvoidmain(String[]args)throwsException{StringfilePathmapped_large_file.dat;longfileSize1024*1024*100;// 100MB// 1. 创建 RandomAccessFile 和 FileChannelRandomAccessFilerafnewRandomAccessFile(filePath,rw);FileChannelchannelraf.getChannel();// 2. 【核心】内存映射// MapMode.READ_WRITE: 读写模式// position: 0, size: fileSizeMappedByteBuffermappedBufferchannel.map(FileChannel.MapMode.READ_WRITE,0,fileSize);// 3. 直接操作内存如同操作数组for(inti0;i1024;i){mappedBuffer.putInt(i*4,i);// 在偏移量 i*4 处写入整数 i}// 4. 强制刷新到磁盘可选确保数据持久化mappedBuffer.force();System.out.println(Data written to mapped file.);// 5. 关闭资源channel.close();raf.close();}}2. 读取大文件示例importjava.io.RandomAccessFile;importjava.nio.MappedByteBuffer;importjava.nio.channels.FileChannel;publicclassMappedFileReader{publicstaticvoidmain(String[]args)throwsException{StringfilePathmapped_large_file.dat;// 1. 创建 RandomAccessFile 和 FileChannelRandomAccessFilerafnewRandomAccessFile(filePath,r);FileChannelchannelraf.getChannel();// 2. 内存映射只读模式MappedByteBuffermappedBufferchannel.map(FileChannel.MapMode.READ_ONLY,0,channel.size());// 3. 随机读取数据intvaluemappedBuffer.getInt(0);// 读取偏移量 0 处的整数System.out.println(Value at offset 0: value);intvalueAt1024mappedBuffer.getInt(1024*4);System.out.println(Value at offset 4096: valueAt1024);// 4. 关闭资源channel.close();raf.close();}}三、 关键注意事项‌资源关闭‌FileChannel 和 SocketChannel 必须显式关闭否则会导致文件描述符泄漏。‌内存映射释放‌MappedByteBuffer 占用的堆外内存不会立即被 GC 回收。若需手动释放可借助 sun.misc.Cleaner非官方 API需谨慎使用或通过反射调用 clean() 方法。‌小文件性能‌对于极小文件 1KB零拷贝的系统调用开销可能高于传统 I/O此时传统 read/write 可能更优。‌平台差异‌transferTo 在 Linux 下性能最佳完整零拷贝在 Windows 下可能退化为部分拷贝实现。

相关新闻

最新新闻

红外小目标检测实战:基于YOLO的数据集与训练策略解析

红外小目标检测实战:基于YOLO的数据集与训练策略解析

简介:目标检测是计算机视觉的核心任务之一,但在红外成像场景下,小目标检测面临目标像素极少、背景噪声强、信噪比低等严峻挑战。YOLO系列模型凭借高效的单阶段检测架构,成为工程落地中广泛采用的解决方案。本文从目标检测的基本概…

2026/8/26 22:46:59
OpenClaw多智能体协作平台:从本地部署到自动化工作流实战

OpenClaw多智能体协作平台:从本地部署到自动化工作流实战

1. 从“小龙虾”到多Agent协作平台:OpenClaw初印象最近在折腾AI Agent自动化流程的朋友,估计没少被各种框架的名字刷屏。LangChain、AutoGen、CrewAI…… 这些名字听起来都挺“正经”的,直到我遇到了一个叫OpenClaw的家伙,图标是只…

2026/8/26 22:46:59
蓝桥杯卡牌题解析:状态机建模与边界处理

蓝桥杯卡牌题解析:状态机建模与边界处理

1. 这道“卡牌”题到底在考什么?——从蓝桥杯十三届国赛B组真题说起如果你正在准备蓝桥杯,尤其是大学B组的国赛冲刺阶段,大概率已经刷过不少模拟题、往届题,甚至能背出几道经典动态规划模板。但2022年十三届国赛B组那道标题只有两…

2026/8/26 22:46:59
PDF签章提取技术详解:从结构解析到图像识别的完整方案

PDF签章提取技术详解:从结构解析到图像识别的完整方案

1. 项目概述:为什么需要从PDF签章文件中提取印章?在数字化办公和电子合同日益普及的今天,PDF签章文件已经成为法律、金融、政务等领域文件流转的标配。一份盖有电子签章的PDF,其法律效力等同于纸质盖章文件。然而,在实…

2026/8/26 22:46:59
信号与系统:卷积与冲激响应的工程本质与应用解析

信号与系统:卷积与冲激响应的工程本质与应用解析

1. 从“黑盒子”到“白盒子”:一个信号工程师的直觉理解每次给新人讲信号与系统,讲到卷积和冲激响应这节,总能看到他们眼神里一闪而过的困惑。公式y(t) x(t) * h(t)写出来简单,但为什么一个信号和另一个叫“冲激响应”的东西卷一…

2026/8/26 22:46:59
Java多进程编程实战:从ProcessBuilder到进程池的完整指南

Java多进程编程实战:从ProcessBuilder到进程池的完整指南

1. 项目概述:为什么Java开发者需要关注多进程?在Java开发者的日常里,多线程(java.lang.Thread)和线程池(java.util.concurrent.ExecutorService)几乎是处理并发任务的标配。我们习惯了在同一个J…

2026/8/26 22:41:59