Netty学习——源码篇10 Netty内存分配ByteBuf基础 备份

1 初始ByteBuf

        ByteBuf是Netty整个结构中最为底层的模块,主要负责把数据从底层I/O读取到ByteBuf,然后传递给应用程序,应用程序处理完成后再把数据封装成ByteBuf写回I/O。所以,ByteBuf是直接与底层打交道的一层抽象。

2 ByteBuf的基本结构

        Netty官方对ByteBuf的描述,具体如下:

        从上面ByteBuf的结构来看,发现ByteBuf有三个非常重要的指针,分别是readerIndex(记录读指针的开始位置)、writerIndex(记录写指针的开始位置)和capacity(缓冲区的总长度),三者的关系是:readerIndex <= writerIndex <= capacity。从0到readerIndex为discardable bytes,表示是无效的;从readerIndex 到 writerIndex 为readable bytes,表示可读数据区;从writerIndex 到capacity位writable bytes,表示这段区间空闲,可以往里面写数据。除了这三个指针,ByteBuf里面其实还有一个指针maxCapacity,它相当于ByteBuf扩容的最大阈值,相应代码如下。

    /*** Returns the maximum allowed capacity of this buffer.  If a user attempts to increase the* capacity of this buffer beyond the maximum capacity using {@link #capacity(int)} or* {@link #ensureWritable(int)}, those methods will raise an* {@link IllegalArgumentException}.*/public abstract int maxCapacity();

        这个maxCapacity指针可以看作是指向capacity之后的这段区间,Netty发现writable bytes写数据超出空间大小时,ByteBuf会提前自动扩容,扩容之后,就有了足够的空间来写数据,同时capacity也会同步更新,maxCapacity就是扩容后capacity的最大值。

3 ByteBuf的重要API

        看一下ByteBuf的基本API,主要包括read()  write()  set()  mark() reset()等方法。请看下表

        在Netty中,ByteBuf大部分功能是在AbstractByteBuf中实现的。

public abstract class AbstractByteBuf extends ByteBuf {//读指针int readerIndex;//写指针int writerIndex;//mark之后的读指针private int markedReaderIndex;//mark之后的写指针private int markedWriterIndex;//最大容量private int maxCapacity;...
}

        下面来看基本读写的骨架代码实现。例如,几个基本的判断读写区间的API,具体实现代码如下:

public abstract class AbstractByteBuf extends ByteBuf {
@Overridepublic boolean isReadable() {return writerIndex > readerIndex;}@Overridepublic boolean isReadable(int numBytes) {return writerIndex - readerIndex >= numBytes;}@Overridepublic boolean isWritable() {return capacity() > writerIndex;}@Overridepublic boolean isWritable(int numBytes) {return capacity() - writerIndex >= numBytes;}@Overridepublic int readableBytes() {return writerIndex - readerIndex;}@Overridepublic int writableBytes() {return capacity() - writerIndex;}@Overridepublic int maxWritableBytes() {return maxCapacity() - writerIndex;}@Overridepublic ByteBuf markReaderIndex() {markedReaderIndex = readerIndex;return this;}@Overridepublic ByteBuf resetReaderIndex() {readerIndex(markedReaderIndex);return this;}@Overridepublic ByteBuf markWriterIndex() {markedWriterIndex = writerIndex;return this;}@Overridepublic ByteBuf resetWriterIndex() {writerIndex = markedWriterIndex;return this;}
}

4 ByteBuf基本分类

        AbstractByteBuf有很多子类,大致可以从三个维度进行分类。

        1、Pooled:池化内存,就是从预先分配好的内存空间中提取一段连续内存封装成一个ByteBuf,分给应用程序使用。

        2、Unsafe:是JDK底层的一个负责I/O操作的对象,可以直接获得对应的内存地址,基于内存地址进行读写操作。

        3、Direct:堆外内存,直接调用JDK底层API进行物理内存分配,不在JVM的堆内存中,需要手动释放。

        综上所述,其实ByteBuf会有6种组合:Pooled(池化内存)和Unpooled(非池化内存);Unsafe和非Unsafe;Heap(堆内存)和Direct(堆外内存)。下图是ByteBuf最重要的继承关系类结构图,通过命名就能一目了然。

        ByteBuf最基本的读写API操作在AbstractByteBuf中已经实现了,其众多子类采用不同的策略来分配内存空间,下表是对重要的几个子类的总结。

 5 ByteBufAllocator内存管理器

        Netty中内存分配有一个顶层的抽象就是ByteBufAllocator,负责分配所有ByteBuf类型的内存。主要有几个重要的API,如下表:

        以上API中为什么没有前面提到的8种类型的内存分配API?下面来看ByteBufAllocator的基本实现类AbstractByteBufAllocator,重点分析主要API的基本实现,比如buffer()方法的代码如下:

public abstract class AbstractByteBufAllocator implements ByteBufAllocator {public ByteBuf buffer() {if (directByDefault) {return directBuffer();}return heapBuffer();}
}

         发现buffer方法中对是否默认支持directBuffer做了判断,如果支持则分配directBuffer,否则分配heapBuffer。

        下面分别来看directBuffer方法和heapBuffer方法的实现,先来看directBuffer方法的代码。

    @Overridepublic ByteBuf directBuffer() {return directBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE);}@Overridepublic ByteBuf directBuffer(int initialCapacity) {return directBuffer(initialCapacity, Integer.MAX_VALUE);}@Overridepublic ByteBuf directBuffer(int initialCapacity, int maxCapacity) {if (initialCapacity == 0 && maxCapacity == 0) {return emptyBuf;}validate(initialCapacity, maxCapacity);return newDirectBuffer(initialCapacity, maxCapacity);}

        directBuffer方法有多个重载方法,最终会调用newDirectBuffer方法,下面看newDirectBuffer的代码。

protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);

        发现newDirectBuffer方法其实是一个抽象方法,最终,交给AbstractByteBufAllocator的子类来实现。同理再来看heapBuffer方法的代码。

   @Overridepublic ByteBuf heapBuffer() {return heapBuffer(DEFAULT_INITIAL_CAPACITY, Integer.MAX_VALUE);}@Overridepublic ByteBuf heapBuffer(int initialCapacity) {return heapBuffer(initialCapacity, Integer.MAX_VALUE);}@Overridepublic ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {if (initialCapacity == 0 && maxCapacity == 0) {return emptyBuf;}validate(initialCapacity, maxCapacity);return newHeapBuffer(initialCapacity, maxCapacity);}

        发现heapBuffer方法最终是调用newHeapBuffer方法,而newHeapBuffer方法也是抽象方法,具体交给AbstractByteBufAllocator的子类实现。AbstractByteBufAllocator的子类主要有两个:PooledByteBufAllocator和UnpooledByteBufAllocator。AbstractByteBufAllocator的子类实现的类结构图如下:

        分析到这里,已经知道directBuffer,heapBuffer和Pooled和Unpooled的分配规则,那么Unsafe和非Unsafe是如何判别的呢?其实是Netty自动判别的。如果操作系统底层支持Unsafe那就采用Unsafe读写,否则采用非Unsafe读写。可以从UnpooledByteBufAllocator的源码中验证,代码如下:

public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {@Overrideprotected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {return PlatformDependent.hasUnsafe() ? new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity): new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);}@Overrideprotected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {ByteBuf buf = PlatformDependent.hasUnsafe() ?UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);return disableLeakDetector ? buf : toLeakAwareBuffer(buf);}
}

        发现在newHeapBuffer方法和newDirectBuffer方法中,分配内存判断PlatformDependent是否支持Unsafe,如果支持则创建Unsafe类型的Buffer,否则创建非Unsafe类型的Buffer,由Netty自动判断。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/294690.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机视觉的技术领域

计算机视觉是一门研究如何使计算机能够“看”和理解图像和视频的科学。它结合了图像处理、模式识别、机器学习、人工智能等多个领域的技术。以下是计算机视觉中的一些关键技术领域。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. …

Netty核心原理剖析与RPC实践11-15

Netty核心原理剖析与RPC实践11-15 11 另起炉灶&#xff1a;Netty 数据传输载体 ByteBuf 详解 在学习编解码章节的过程中&#xff0c;我们看到 Netty 大量使用了自己实现的 ByteBuf 工具类&#xff0c;ByteBuf 是 Netty 的数据容器&#xff0c;所有网络通信中字节流的传输都是…

C++其他语法..

1.运算符重载 之前有一个案例如下所示 其中我们可以通过add方法将两个点组成一个新的点 class Point {friend Point add(Point, Point);int m_x;int m_y; public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x <<…

十四.PyEcharts基础学习

目录 1-PyEcharts介绍 优点&#xff1a; 安装: 官方文档&#xff1a; 2-PyEcharts快速入门 2.1 第一个图表绘制 2.2 链式调用 2.3 opeions配置项 2.4 渲染图片文件 2.5 使用主题 3-PyEcharts配置项 3.1 初始化配置项InitOpts InitOpts 3.2 全局配置项set_global_o…

SQLBolt,一个练习SQL的宝藏网站

知乎上有人问学SQL有什么好的网站&#xff0c;这可太多了。 我之前学习SQL买了本SQL学习指南&#xff0c;把语法从头到尾看了个遍&#xff0c;但仅仅是心里有数的程度&#xff0c;后来进公司大量的写代码跑数&#xff0c;才算真真摸透了SQL&#xff0c;知道怎么调优才能最大化…

时序数据库IoTDB:功能详解与行业应用

一文读懂时序数据库 IoTDB。 01 为什么需要时序数据库 解释时序数据库前&#xff0c;先了解一下何谓时序数据。 时序数据&#xff0c;也称为时间序列数据&#xff0c;是指按时间顺序记录的同一统计指标的数据集合。这类数据的来源主要是能源、工程、交通等工业物联网强关联行业…

基于Arduino IDE 野火ESP8266模块 文件系统LittleFS 的开发

一、文件系统LittleFS的介绍 LittleFS是一个为微控制器设计的轻量级、可靠且高性能的文件系统。它专为嵌入式设备打造&#xff0c;拥有占用空间小、对硬件要求低的特点&#xff0c;同时保证在断电情况下数据的完整性和稳定性。 1.设计与特点 LittleFS的设计旨在提供嵌入式系统所…

Pytorch for training1——read data/image

blog torch.utils.data.Dataset create dataset with class torch.utils.data.Dataset automaticly import torch from torch.utils.data import Datasetclass MyDataset(Dataset):def __init__(self, data):self.data datadef __getitem__(self, index):# 根据索引获取样本…

数据可视化高级技术(Echarts)

目录 &#xff08;一&#xff09;数据可视化概念及Echarts基础知识 数据可视化的好处&#xff1a; 数据可视化的目标 数据可视化的基本流程 &#xff08;二&#xff09;数据图表 类别比较图表&#xff1a; 数据关系图表&#xff1a; 数据分布图表&#xff1a; 时间序列…

智能文档合规检测系统:在央企国企招标采购领域的应用

一、背景介绍 在央企国企采购过程中&#xff0c;合规性是一个不可忽视的重要方面。采购方需要确保供应商的资质、业绩、规模等条件符合采购要求&#xff0c;同时避免设置不合理的条件限制或排斥潜在供应商。为了提高采购效率和确保合规性&#xff0c;智能文档合规检测系统应运…

网页的血液——javascript

JavaScript 基础知识概述 1. JavaScript 介绍 JavaScript 是一种高级的、解释型的编程语言&#xff0c;它是一种基于对象的、事件驱动的语言&#xff0c;它允许开发者创建动态的网页。JavaScript 是一种脚本语言&#xff0c;它可以嵌入到 HTML 中&#xff0c;或者作为外部文件…

YOLOv9改进策略 :主干优化 | 无需TokenMixer也能达成SOTA性能的极简ViT架构 | CVPR2023 RIFormer

💡💡💡本文改进内容: token mixer被验证能够大幅度提升性能,但典型的token mixer为自注意力机制,推理耗时长,计算代价大,而RIFormers是无需TokenMixer也能达成SOTA性能的极简ViT架构 ,在保证性能的同时足够轻量化。 💡💡💡RIFormerBlock引入到YOLOv9,多个数…

ADS-B及雷达显示终端8.4

#更新内容# 本次软件更新内容不少&#xff0c;但可见部分不多。主要更新集中的系统后台部分。后台更新内容包括&#xff1a; #后台更新内容# 1、增加了对部分特殊雷达编码格式的支持。应甲方要求&#xff0c;对部分国产雷达及其特殊的雷达编码协议进行了支持&#xff0c;增加了…

OpenHarmony无人机MAVSDK开源库适配方案分享

MAVSDK 是 PX4 开源团队贡献的基于 MavLink 通信协议的用于无人机应用开发的 SDK&#xff0c;支持多种语言如 C/C、python、Java 等。通常用于无人机间、地面站与通信设备的消息传输。 MAVLink 是一种非常轻量级的消息传递协议&#xff0c;用于与无人机&#xff08;以及机载无…

【好书推荐4】图机器学习

【好书推荐4】图机器学习 写在最前面编辑推荐内容简介作者简介目录前言/序言本书读者内容介绍 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能…

分月饼 java题解

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in); int m sc.nextInt(); // 读取员工数量mint n sc.nextInt(); // 读取月饼数量n// 调用distribute方法并打印返回的分配方法总数//先默认每人分一个…

SmartChart的部署以及可能遇见的报错解决方案

简介 数据可视化是一种将数据转化为图形的技术&#xff0c;可以帮助人们更好地理解和分析数据。但是&#xff0c;传统的数据可视化开发往往需要编写大量的代码&#xff0c;或者使用复杂的拖拽工具&#xff0c;不仅耗时耗力&#xff0c;而且难以实现个性化的需求。有没有一种更…

SwiftUI Swift 显示隐藏系统顶部状态栏

Show me the code // // TestHideSystemTopBar.swift // pandabill // // Created by 朱洪苇 on 2024/4/1. //import SwiftUIstruct TestHideSystemTopBar: View {State private var isStatusBarHidden falsevar body: some View {Button {withAnimation {self.isStatusBa…

67、yolov8目标检测和旋转目标检测算法batchsize=1/6部署Atlas 200I DK A2开发板上

基本思想:需求部署yolov8目标检测和旋转目标检测算法部署atlas 200dk 开发板上 一、转换模型 链接: https://pan.baidu.com/s/1hJPX2QvybI4AGgeJKO6QgQ?pwd=q2s5 提取码: q2s5 from ultralytics import YOLO# Load a model model = YOLO("yolov8s.yaml") # buil…

VUE3——生命周期

Vue3.0中可以继续使用Vue2.x中的生命周期钩子&#xff0c;但有有两个被更名&#xff1a; beforeDestroy改名为 beforeUnmountdestroyed改名为 unmounted Vue3.0也提供了 Composition API 形式的生命周期钩子&#xff0c;与Vue2.x中钩子对应关系如下&#xff1a; beforeCreate&g…