我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Netty分布式ByteBuf的分类方式源码解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Netty分布式ByteBuf的分类方式源码解析

上一小节简单介绍了AbstractByteBuf这个抽象类, 这一小节对其子类的分类做一个简单的介绍

ByteBuf根据不同的分类方式 会有不同的分类结果

我们首先看第一种分类方式

1.Pooled和Unpooled

pooled是从一块内存里去取一段连续内存封装成byteBuf

具体标志是类名以Pooled开头的ByteBuf, 通常就是Pooled类型的ByteBuf, 比如: PooledDirectByteBuf或者pooledHeapByteBuf

有关如何分配一块连续的内存, 我们之后的章节会讲到

Unpooled是分配的时候直接调用系统api进行实现, 具体标志是以Unpooled开头的ByteBuf, 比如UnpooledDirectByteBuf, UnpooledHeapByteBuf

再看第二种分类方式

2.基于直接内存的ByteBuf和基于堆内存的ByteBuf

基于直接内存的ByteBuf, 具体标志是类名中包含单词Direct的ByteBuf, 比如UnpooledDirectByteBuf, PooledDirectByteBuf等

基于堆内存的ByteBuf, 具体标志是类名中包含单词heap的ByteBuf, 比如UnpooledHeapByteBuf, PooledHeapByteBuf

结合以上两种方式, 这里通过其创建的方式去简单对其分类做个解析

这里第一种分类的Pooled, 也就是分配一块连续内存创建byteBuf, 这一小节先不进行举例, 会在之后的小节讲到

这里主要就看Unpooled, 也就是调用系统api的方式创建byteBuf, 在直接内存和堆内存中有什么区别

这里以UnpooledDirectByteBuf和UnpooledHeapByteBuf这两种为例, 简单介绍其创建方式:

首先看UnpooledHeapByteBuf的byetBuf, 这是基于内存创建ByteBuf, 并且是直接调用系统api

我们看UnpooledHeapByteBuf的byetBuf的构造方法:

protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
     this(alloc, new byte[initialCapacity], 0, 0, maxCapacity);
 }

这里调用了自身的构造方法, 参数中创建了新的字节数组, 初始长度为初始化的内存大小, 读写指针初始位置都是0, 并传入了最大内存大小

从这里看出, 有关堆内存的Unpooled类型的分配, 是通过字节数组进行实现的

再往下跟:

protected UnpooledHeapByteBuf(ByteBufAllocator alloc, byte[] initialArray, int maxCapacity) {
    this(alloc, initialArray, 0, initialArray.length, maxCapacity);
}

继续跟:

private UnpooledHeapByteBuf(
        ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {
    super(maxCapacity);
    //忽略验证代码
    this.alloc = alloc;
    setArray(initialArray);
    setIndex(readerIndex, writerIndex);
}

跟到setAarry方法中:

private void setArray(byte[] initialArray) {
    array = initialArray;
    tmpNioBuf = null;
}

将新创建的数组赋值为自身的array属性

回到构造函数中, 跟进setIndex方法:

public ByteBuf setIndex(int readerIndex, int writerIndex) {
    //忽略验证代码
    setIndex0(readerIndex, writerIndex);
    return this;
}

这里实际上是调用了AbstractByteBuf的setIndex方法

我们跟进setIndex0方法中:

final void setIndex0(int readerIndex, int writerIndex) {
    this.readerIndex = readerIndex;
    this.writerIndex = writerIndex;
}

这里设置了读写指针, 根据之前的调用链我们知道, 这里将读写指针位置都设置为了0

介绍完UnpooledHeapByteBuf的初始化, 我们继续看UnpooledDirectByteBuf这个类的构造, 顾明思议, 是基于堆外内存, 并且同样也是调用系统api的方式进行实现的

我们看其构造方法:

protected UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
    super(maxCapacity);
    //忽略验证代码
    this.alloc = alloc;
    setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
}

我们关注下setByteBuffer中的参数ByteBuffer.allocateDirect(initialCapacity)

我们在这里看到, 这里通过jdk的ByteBuffer直接调用静态方法allocateDirect分配了一个基于直接内存的ByteBuffer, 并设置了初始内存

再跟到setByteBuffer方法中:

private void setByteBuffer(ByteBuffer buffer) {
    ByteBuffer oldBuffer = this.buffer;
    if (oldBuffer != null) {
        //代码忽略
    }
    this.buffer = buffer;
    tmpNioBuf = null;
    capacity = buffer.remaining();
}

我们看到在这里将分配的ByteBuf设置到当前类的成员变量中

以上两种实例, 我们会对上面所讲到的两种分类有个初步的了解

这里要注意一下, 基于堆内存创建ByteBuf, 可以不用考虑对象回收, 因为虚拟机会进行垃圾回收, 但是堆外内存在虚拟机的垃圾回收机制的作用域之外, 所以这里要考虑手动回收对象

最后, 我们看第三种分类方式:

3.safe和unsafe

首先从名字上看, safe代表安全的, unsafe代表不安全的

这个安全与不安全的定义是什么呢

其实在我们jdk里面有unsafe对象, 可以通过unsafe对象直接拿到内存地址, 基于内存地址可以进行读写操作

如果是Usafe类型的byteBuf, 则可以直接拿到byteBuf在jvm中的具体内存, 可以通过调用jdk的Usafe对象进行读写, 所以这里代表不安全

而非Usafe不能拿到jvm的具体内存, 所以这里代表安全

具体标志是如果类名中包含unsafe这个单词的ByteBuf, 可以认为是一个unsafe类型的ByteBuf, 比如PooledUnsafeHeapByteBuf或者PooledUnsafeDirectByteBuf

以PooledUnsafeHeapByteBuf的_getByte方法为例:

protected byte _getByte(int index) {
    return UnsafeByteBufUtil.getByte(memory, idx(index));
}

这里memory代表byebuffer底层分配内存的首地址, idx(index)代表当前指针index距内存memory的偏移地址, UnsafeByteBufUtil的getByte方法, 就可以直接通过这两个信息通过jdk底层的unsafe对象拿到jdk底层的值

有关AbstractByteBuf的主要实现类和继承关系, 如下图所示:

以上就是Netty分布式ByteBuf的分类方式源码解析的详细内容,更多关于Netty分布式ByteBuf分类方式的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Netty分布式ByteBuf的分类方式源码解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

分布式Netty源码分析

这篇文章主要介绍了分布式Netty源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇分布式Netty源码分析文章都会有所收获,下面我们一起来看看吧。服务器端demo看下一个简单的Netty服务器端的例子pu
2023-06-29

分布式Netty源码EventLoopGroup分析

这篇文章主要介绍“分布式Netty源码EventLoopGroup分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“分布式Netty源码EventLoopGroup分析”文章能帮助大家解决问题。Ev
2023-06-29

Netty分布式flush方法刷新buffer队列源码分析

本文小编为大家详细介绍“Netty分布式flush方法刷新buffer队列源码分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“Netty分布式flush方法刷新buffer队列源码分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入
2023-06-29

Netty分布式ByteBuf使用subPage级别内存分配的方法

这篇文章主要介绍“Netty分布式ByteBuf使用subPage级别内存分配的方法”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Netty分布式ByteBuf使用subPage级别内存分配的方法”
2023-06-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录