大致意思就是通过 Native 方法获取内存映射的地址,如果失败,手动 GC 再次映射 。
最后通过内存映射的地址实例化出 MappedByteBuffer,MappedByteBuffer 本身是一个抽象类,其实这里真正实例化出来的是 DirectByteBuffer 。
DirectByteBuffer
DirectByteBuffer 继承于 MappedByteBuffer,从名字就可以猜测出开辟了一段直接的内存,并不会占用 JVM 的内存空间 。
上一节中通过 Filechannel 映射出的 MappedByteBuffer 其实际也是 DirectByteBuffer,当然除了这种方式,也可以手动开辟一段空间:
ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(100);如上开辟了 100 字节的直接内存空间 。
Channel-to-Channel 传输
经常需要从一个位置将文件传输到另外一个位置,FileChannel 提供了 transferTo() 方法用来提高传输的效率,首先看一个简单的实例:
public class ChannelTransfer { public static void main(String[] argv) throws Exception { String files[]=new String[1]; files[0]="D://db.txt"; catFiles(Channels.newChannel(System.out), files); } private static void catFiles(WritableByteChannel target, String[] files) throws Exception { for (int i = 0; i < files.length; i++) { FileInputStream fis = new FileInputStream(files[i]); FileChannel channel = fis.getChannel(); channel.transferTo(0, channel.size(), target); channel.close(); fis.close(); } }}通过 FileChannel 的 transferTo() 方法将文件数据传输到 System.out 通道,接口定义如下:
public abstract long transferTo(long position, long count, WritableByteChannel target) throws IOException;几个参数也比较好理解,分别是开始传输的位置,传输的字节数,以及目标通道;transferTo() 允许将一个通道交叉连接到另一个通道,而不需要一个中间缓冲区来传递数据 。
注:这里不需要中间缓冲区有两层意思:第一层不需要用户空间缓冲区来拷贝内核缓冲区,另外一层两个通道都有自己的内核缓冲区,两个内核缓冲区也可以做到无需拷贝数据 。
Netty 零拷贝Netty 提供了零拷贝的 Buffer,在传输数据时,最终处理的数据会需要对单个传输的报文,进行组合和拆分,NIO 原生的 ByteBuffer 无法做到
Netty 通过提供的 Composite(组合)和 Slice(拆分)两种 Buffer 来实现零拷贝 。
看下面一张图会比较清晰:

文章插图
TCP 层 HTTP 报文被分成了两个 ChannelBuffer,这两个 Buffer 对我们上层的逻辑(HTTP 处理)是没有意义的 。
但是两个 ChannelBuffer 被组合起来,就成为了一个有意义的 HTTP 报文,这个报文对应的 ChannelBuffer,才是能称之为“Message”的东西,这里用到了一个词“Virtual Buffer” 。
可以看一下 Netty 提供的 CompositeChannelBuffer 源码:
【深入探秘 Netty、Kafka 中的零拷贝技术!】
public class CompositeChannelBuffer extends AbstractChannelBuffer { private final ByteOrder order; private ChannelBuffer[] components; private int[] indices; private int lastAccessedComponentId; private final boolean gathering; public byte getByte(int index) { int componentId = componentId(index); return components[componentId].getByte(index - indices[componentId]); } ...省略...
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 总结的非常详细 深入理解linux系统的目录结构
- 健走有啥好处
- 深入浅出微服务架构:一分钟让你轻松上手Docker容器
- 吃透移动端 H5 响应式布局 |深入原理到目前最佳实践方案
- 心理探秘:如何辨别不自信的男人?
- 中国茶营销,茶企需深入领会中国茶道本真
- 8分钟带你深入浅出搞懂Nginx
- 三星堆为何不敢深入研究? 三星堆研究不再公布
- 普洱茶之发源地探秘
- 黔台茶文化交流座谈会 两岸业者深入交流
