(二) netty非池化内存的表示:UnpooledHeapByteBuf和UnpooledDirectByteBuf

02 记一次 netty 内存泄露 前言 最近在一个 jt809 的项目中碰到了这样的一个问题 最开始 对方传输给我们的车辆数量不多的情况下, 系统一直很稳健 但是 由于之前又对接了大量的车辆, 然后 之后出现了一次 OutOfDirectMemoryError, 然后 当时 临时重启了一下 然后 过了一周左右的时间(7, 8天), 服务再一次OutOfDirectMemoryError 大概的错误信息是这样 Exception in thread "main" io.netty.util.internal.OutO...... 阅读详情

1 概述

从最基础的ByteBuf开始讲解netty的内存分配,是为了后续更清楚地了解netty内存池的分配技术。目标是,了解各种ByteBuf本质上是什么?

netty提供了众多的ByteBuf实现,而在我们该系列文章中,我们按内存分配的算法来分类,分为非池化ByteBuf和池化的ByteBuf。而两个主力的非池化字节缓冲UnpooledHeapByteBuf和UnpooledDirectByteBuf,正是本文的主角。为了更有条理地了解它们,我们先看继承关系:
在这里插入图片描述

1.1 ByteBuf和AbstractByteBuf讲解

netty ByteBuf对nio ByteBuffer进行了改良,引入读写下标readerIndex和writerIdnex,分别用于读写的控制。它们有如下关系:

0  <= readerIndex  <= writerIndex <= capacity

本文将主要考察非池化字节缓存的分配、读写和释放。读写方法以如下两个API为例:

–ByteBuf writeBytes(byte[] src, int srcIndex, int length),将指定字节数组写入到本ByteBuf中;

–ByteBuf readBytes(byte[] dst, int dstIndex, int length),将该ByteBuf内容读取到指定字节数组。

读写的主逻辑,都在AbstractByteBuf类中,采用模板方法的设计模式,留真正进行内存读写的方法延迟到子类实现(因为各种ByteBuf读写的内存区域不同,读写方式也就有差异),比如writeBytes:

public ByteBuf writeBytes(byte[] src, int srcIndex, int length) {
  ensureWritable(length);
  setBytes(writerIndex, src, srcIndex, length);
  writerIndex += length;
  return this;
}

可以看到,writerIndex下标检查和移动,都在AbstractByteBuf进行,因为这些都是公共的相同的操作。而真正写内存setBytes是个抽象方法:

public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length);

readBytes也是类似:

public ByteBuf readBytes(byte[] dst, int dstIndex, int length) {
  checkReadableBytes(length);
  getBytes(readerIndex, dst, dstIndex, length);
  readerIndex += length;
  return this;
}

真正读内存的getBytes是个抽象方法:

public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);

setBytes和getBytes的实现,将在后面UnpooledHeapByteBuf和UnpooledDirectByteBuf的讲解中进行分析。

1.2 引用计数器

从类的继承关系图,可以看到ByteBuf实现了ReferenceCounted接口,这个接口主要用于对ByteBuf进行引用计数。这个功能非常重要,是netty内存池实现的基础组件之一。它主要有两个方法:

–retain()将引用计数器加1;

–release()将引用计数器减去1。

其功能的实现主要在AbstractReferenceCountedByteBuf中。

AbstractReferenceCountedByteBuf

它有一个refCnt属性,用于引用计数:

private volatile int refCnt = 2;

这里netty为了使用位运算提高效率,将refCnt数值保存为偶数,真正的引用个数,需要转换得到。比如2代表有一个引用,4代表2个引用,6代表3个引用,8代表4个引用,10代表5个引用等等…,如果检查到refCnt为奇数,会直接报错。

刚创建时refCnt=2,所以一个ByteBuf一创建,就有了一个引用了。

每次调用release()减少一个引用,同时检查引用个数是否已经等于0,如果等于0了,就调用deallocate()方法释放内存,并且释放内存有重试机制,一次释放不掉,会不断地进行重试,直到成功释放。而deallocate()也是个抽象方法,由子类决定如何释放:

/**
* Called once {@link #refCnt()} is equals 0.
*/
protected abstract void deallocate();

关于对象引用计数对象的使用的一些最佳实践,见netty文档:Reference counted objects

讲完这些基础后,再来看看本文的主角UnpooledHeapByteBuf和UnpooledDirectByteBuf,就容易得多。

2 非池化堆内存UnpooledHeapByteBuf

堆内的字节缓冲,本质上是字节数组的封装。它的声明周期和字节数组的创建、使用、释放对应,所以它的主要属性就是这个字节数组:

byte[] array;

而它的可用容量capacity,就是该数组的长度。我们看看这个数组是怎么分配的,从构造器开始:

public UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
  // 省略其他代码
  setArray(allocateArray(initialCapacity));
  setIndex(0, 0);
}

主要是通过allocateArray方法创建一个字节数组,然后通过setArray赋值给array属性:

protected byte[] allocateArray(int initialCapacity) {
	return new byte[initialCapacity];
}

setArray也简单直接,为了一探究竟也给出源码:

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

UnpooledHeapByteBuf的读写

说完分配之后我们看读写。读写的主体流程,上文已有讲解,并留了setBytes/getBytes两个抽象方法,到本节进行实现分析。先来看看写字节缓冲用到的setBytes是怎么把字节流设置到UnpooledHeapByteBuf:

1、做下标检查

2、通过数组拷贝直接将源字节流,拷贝到UnpooledHeapByteBuf对象的array属性中。如下:

@Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
  checkSrcIndex(index, length, srcIndex, src.length);
  System.arraycopy(src, srcIndex, array, index, length);
  return this;
}

再来看看getBytes,也是数组拷贝,只是数据的源头变成了UnpooledHeapByteBuf的字节数组array:

public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
  checkDstIndex(index, length, dstIndex, dst.length);
  System.arraycopy(array, index, dst, dstIndex, length);
  return this;
}

UnpooledHeapByteBuf的释放

上文讲解引用计数器时,提到了如果计数器为0了,就会调用deallocate()方法进行释放,具体如何释放,是这个子类实现的。现在来看看在UnpooledHeapByteBuf中的释放,其本质是去掉指向字节数组的引用,这样它就可以被GC掉,达到释放的目的:

@Override
protected void deallocate() {
  freeArray(array);
  array = EmptyArrays.EMPTY_BYTES;
}

protected void freeArray(byte[] array) {
  // NOOP
}

2.1 UnpooledUnsafeHeapByteBuf

UnpooledUnsafeHeapByteBuf和UnpooledHeapByteBuf的不同之处,在于前者是通过Unsafe来分配字节数组的:

protected byte[] allocateArray(int initialCapacity) {
  return PlatformDependent.allocateUninitializedArray(initialCapacity);
}

最终,会调用到jdk.internal.misc.Unsafe类的allocateUninitializedArray方法,通过该方法创建字节数组性能会更高一些。另外,通过allocateUninitializedArray来分配数组也是有条件的,jdk版本必须是Jdk9(included)以上,并且数组的大小要大于1024字节,要不然还是直接创建byte数组并返回。jdk9的Unsafe类参考:jdk.internal.misc.Unsafe。

UnpooledUnsafeHeapByteBuf后续对字节数组的读写,也通过Unsafe类来进行,不过这时使用的Unsafe类就是我们用得较多的sun.misc.Unsafe类,通过这种方式进行字节数组的读写,据说性能也会高些。

除此之外,UnpooledUnsafeHeapByteBuf和UnpooledHeapByteBuf没有其他差别。

3 非池化的直接内存UnpooledDirectByteBuf

UnpooledDirectByteBuf其实是对java.nio.DirectByteBuffer的封装,所以它的主要属性有java.nio.ByteBuffer和一个代表容量从capacity:

private ByteBuffer buffer;
private int capacity;

调用其构造器进行创建时,就会创建java.nio.DirectByteBuffer,从而分配到位于堆外的直接内存。关于java.nio.DirectByteBuffer的内存分配和使用,可以参考:java.nio.DirectByteBuffer的分配与回收源码剖析。

这里还是照例给出UnpooledDirectByteBuf创建DirectByteBuffer的调用点:

    public UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
				// 省略...
        this.alloc = alloc;
        setByteBuffer(allocateDirect(initialCapacity));
    }

在allocateDirect方法中,分配直接内存:

protected ByteBuffer allocateDirect(int initialCapacity) {
  return ByteBuffer.allocateDirect(initialCapacity);
}

==============java.nio.ByteBuffer中================
public static ByteBuffer allocateDirect(int capacity) {
  return new DirectByteBuffer(capacity);
}

组合了nio的ByteBuffer后,UnpooledDirectByteBuf的读写都转换为ByteBuffer的读写,比如setBytes:

public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
  checkSrcIndex(index, length, srcIndex, src.length);
  ByteBuffer tmpBuf = internalNioBuffer();
  tmpBuf.clear().position(index).limit(index + length);
  tmpBuf.put(src, srcIndex, length);
  return this;
}

先检查下标,然后通过internalNioBuffer()方法创建出一个tmpBuf,这个tmpBuf和源ByteBuffer共享原来的内存段,但是有独立的下标。对tmpBuf进行写入,变更会反映到源ByteBuffer。注意,setBytes不会改变netty的writerIndex,下标的修改在父类writeBytes方法中,见前文。

getBytes也是转换为对nio ByteBuffer的读取,只展示关键代码:

  tmpBuf.clear().position(index).limit(index + length);
  tmpBuf.get(dst, dstIndex, length);

而UnpooledDirectByteBuf的释放,是通过反射调用java.nio.DirectByteBuffer的cleaner对象的clean()方法完成的,具体怎么释放,可以参考:java.nio.DirectByteBuffer的分配与回收源码剖析

3.1 UnpooledUnsafeDirectByteBuf

UnpooledUnsafeDirectByteBuf和非Unsafe版本UnpooledDirectByteBuf,都是通过new DirectByteBuffer(capacity)来创建直接内存。不同之处在于,前者会将分配到的直接内存的起始地址存起来:

long memoryAddress;

final void setByteBuffer(ByteBuffer buffer, boolean tryFree) {
  // 省略...
  memoryAddress = PlatformDependent.directBufferAddress(buffer);
  // 省略...
}

将直接内存的起始地址存起来之后,读写就可以不通过nio ByteBuffer来进行,而是直接对内存进行读写,性能上会好一些。

除此之外,其他方面基本相同,包括释放也都是通过反射调用DirectByteBuffer的cleaner来完成。

3.2 UnpooledUnsafeNoCleanerDirectByteBuf

该类继承自UnpooledUnsafeDirectByteBuf,不过它分配直接内存时,是通过Unsafe.allocateMemory(int capacity)的调用,先分配到直接内存,拿到直接内存起始地址address,再以address为参数,反射调用DirectByteBuffer的以下构造器创建DirectByteBuffer对象:

DirectByteBuffer(long addr, int cap, Object ob)

注意,DirectByteBuffer的这个构造器,不会创建cleaner对象,这也就是该类名有NoCleaner关键字的原因。

既然没有cleaner,释放内存时也就不能通过cleaner来释放,所以释放UnpooledUnsafeNoCleanerDirectByetBuf的内存时,是直接调用Unsafe.freeMemory(long address)来完成释放的。

完~

基于ESP32-S3与模块化设计的立创桌面充电站:从硬件架构到Web控制实战 本文详细介绍了基于ESP32-S3与模块化设计的立创桌面充电站项目,涵盖从硬件架构到Web控制的全流程实战。项目采用模块化设计,支持自由组合快充模块,并通过ESP32-S3实现智能监控,用户可通过本地网页实时查看各接口电压、电流与功率数据。文章重点解析了基板、连接板与充电模块三大核心部件的设计,特别是大电流PCB的“开窗贴铜”处理技巧,并提供了固件刷写与Web控制面板的配置指南。 阅读详情

相关推荐

从门禁到支付:Uniapp+NFC开发避坑指南(支持Mifare Classic)

本文详细介绍了Uniapp结合NFC技术开发门禁与支付系统的实战指南,特别针对Mifare Classic卡片进行深度优化。内容涵盖环境配置、设备兼容性处理、卡片安全机制解析以及高性能读写优化策略,帮助开发者快速实现跨平台的智能硬件交互解决方案。

t1u2v的博客 750

Netty ByteBuf源码解析

作者: LemonNan 原文链接: https://juejin.im/post/6844903983530655751 Netty 的 ByteBuf 类型 Pooled(池化)、Unpooled(非池化) Direct(直接缓冲区/堆外)、Heap(jvm堆内) unsafe(unsafe 调用的本地方法)、safe(一般也不会这么说, 这是相对于 unsafe, 指的jvm 堆内的操作) Netty 默认都会优先使用 unsafe 的实现 池化/非池化(Pooled/Unpo.

一个程序员 1667

HAL库硬件SPI驱动ST7735 TFT屏幕:从零实现高效刷屏与图形绘制

本文详细介绍了如何使用STM32的HAL库硬件SPI驱动ST7735 TFT屏幕,从硬件连接到SPI配置优化,再到图形绘制与文本显示的实现。重点分享了DMA传输、局部刷新等高级优化技巧,显著提升刷屏效率,帮助开发者快速掌握屏幕驱动技术并应用于实际项目。

pink的博客 740

Netty入门P11

数据在InboundHandler链上的传递 Server示例代码: /** * @program: learnnetty * @description: 事件传播 * @create: 2020-05-08 16:40 **/ public class Server { public static void main(String[] args) { NioEventLoopGroup workerGroup = new NioEventLoopGroup();

qq_40462579的博客 2004

Multisim实战:从零搭建体温检测报警电路(附完整仿真文件+调试技巧)

本文详细介绍了如何使用Multisim从零搭建体温检测报警电路,涵盖LM35温度传感器、LM358运算放大器等核心器件的选型与连接,以及信号调理、阈值比较和数码管显示等关键电路设计。附赠完整仿真文件和实用调试技巧,帮助电子工程初学者快速掌握体温温度检测系统的设计与实现。

weixin_28285943的博客 292

解决/usr/lib64/libstdc++.so.6和/lib64/libc.so.6版本过低问题

在CentOS7.0中编译好MySQL5.7.14之后,然后在CentOS6.5中初始化MySQL,执行:/usr/local/mysql/bin/mysqld --version出现如下问题:./bin/mysqld: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by ./bin/mysqld)

poxiaonie的博客 2万+

Java基础之《netty(17)—Unpooled类》

写的时候writerIndex先加,readerIndex在后面追赶,只能读到writerIndex的位置。通过给定的数据和字符编码返回一个ByteBuf对象(类似于NIO中的ByteBuffer但有区别)。1、netty提供一个专门用来操作缓冲区(即netty的数据容器)的工具类。不指定索引,用readByte()方法读,readerIndex会增加。Unpooled类获取netty的数据容器ByteBuf的基本使用。4、readerIndex属性和writerIndex属性。

csj50的专栏 1408

CDD数据库文件制作(二)——DTC配置

1.DTC库 2.新建DTC DTC相关介绍:https://blog.youkuaiyun.com/LOVE135149/article/details/122565443 ① 选择DTC数据库 ② 点击新建DTC ③ DTC参数编辑 3.将DTC库中的DTC加载到Variant中 找到Fault Memory的DTC Table,鼠标放在DTC Table区域,右键点击选择Copy … Reference from Available DTCs…,即可将DTC库中的故障码加载至Variant中。 虽然选择Co

LOVE135149的博客 1万+

PooledByteBuf分配及回收之六PooledUnsafeDirectByteBuf初始化

final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> PooledByteBuf的属性 属性 含义 值 private final Handle<PooledByteBuf<T>> recyclerHandle 回收处理句柄 这里的T是ByteBuffer protected...

AnY11的专栏 6563

4、接收天线:接收电压、功率和传输系数

本文详细探讨了接收天线的性能参数,包括接收电压、功率和传输系数,通过建立等效电路模型分析接收偶极子的电流和开路电压,并定义电压和功率传输函数。研究揭示了天线长度、工作频率及极化失配对传输性能的影响,并提出了优化接收天线性能的策略,为天线系统的设计与优化提供了理论支持。

ll5678的博客 233

【硬件工程师面经整理18_Smith圆图】

若文中任何内容侵犯了您的合法权益,请相关权益人及时与我联系,我将立即进行核实并采取适当措施,包括但不限于删除相关内容或更新文章以消除影响。**在Smith圆图上,源阻抗表示为圆心,而负载阻抗表示为圆图上的一个点。具体来说,通过将负载阻抗在Smith圆图上移动到特定位置,使其与传输线特性阻抗形成纯电阻或纯电抗的组合,从而实现匹配。例如,反射系数表示为Smith圆图上的一个点,而驻波比则表示为圆图上两个点之间的距离。Smith圆图是用于阻抗匹配和网络分析的工具,它是一种将复阻抗表示为坐标的图形。

LeeYLong的博客 651

Netty篇:ByteBuf之堆外内存与回收策略源码分析(非池化)

上文描述过,ByteBuf根据内存分可以分为堆内存和堆外内存实现,此处以非池化实现介绍,两个重要子类是UnpooledHeapByteBuf和UnpooledDirectByteBuf,因为堆外内存和堆内存除了内存分配之外,其他实现十分相似,先简单描述下堆内存实现,然后重点分析堆外内存的分配及回收策略

走在路上 1932

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Netty学习之旅----ByteBuf源码解读之初探UnpooledHeapByteBuf、UnpooledDirectByteBuf

首先,我们再看一下 ByteBuf 的类设计图,从中更进一步了解ByteBuf。 ByteBuf 继承自 ReferenceCounted,引用计数,也就是说 ByteBuf 的内存回收使用的是引用计数器来实现。 UnpooledHeapByteBuf 是非池化的堆内存实现,而 UnpooledDirectByteBuf 是非池化的堆外内存(直接内存)。非池化的ByteBuf 就是利用完之...

中间件兴趣圈 1万+

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Netty堆内存字节缓冲区深度解析

摘要:UnpooledHeapByteBuf是Netty基于JVM堆内存的非池化字节缓冲区实现,采用byte[]作为底层存储,具有非池化设计、堆内存管理、引用计数等特点。其核心机制包括:1)通过System.arraycopy实现高效容量调整;2)零拷贝NIO缓冲区转换;3)索引边界控制确保安全访问。优化子类UnpooledUnsafeHeapByteBuf通过Unsafe API跳过数组初始化和边界检查提升性能。对比直接内存实现UnpooledDirectByteBuf,堆内存版本更适合高频创建的临时缓冲

lifallen的博客 888

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Netty学习——源码篇11 Netty非池化内存分配

现在来看UnpooledByteBufAllocator的内存分配原理。通过调用PlatformDependent.hasUnsafe()方法来判断操作系统是否支持Unsafe,如果支持Unsafe则创建UnpooledUnsafeHeapByteBuf类,否则创建UnpooledHeapByteBuf类。

geminigoth的博客 1287

Netty学习——源码篇11 Netty非池化内存分配 备份

现在来看UnpooledByteBufAllocator的内存分配原理。通过调用PlatformDependent.hasUnsafe()方法来判断操作系统是否支持Unsafe,如果支持Unsafe则创建UnpooledUnsafeHeapByteBuf类,否则创建UnpooledHeapByteBuf类。

geminigoth的博客 1034

读书笔记:《Netty进阶之路》——netty缓冲区、缓冲区释放、内存池

  第3章提出问题:“缓冲区未正确释放导致Netty内存池泄露”,引出Netty内存管理方式介绍;第4张提出问题:“ByteBuf使用不当导致报错、程序无法正常运行”,引出ByteBuf的使用方式和原理。我颠倒一下顺序,先回顾ByteBuf的正确使用和实现原理,后回顾Netty内存池技术。 1 Netty缓冲区——ByteBuf   Netty的ByteBuf是一个抽象类,是Netty管辖的内存,...

qq_32717909的博客 5431

netty中ByteBuf部分的分析

好久木有看代码了,今天把以前读netty源码的时候一直没有看的Buffer部分粗略的看了下,刚开始主要是觉得buffer这个包里面类太多了,觉得比较麻烦,而且相对理解整个netty的设计不太影响,所以就拖着没看,但是记得有一次跟支付宝的技术问了我关于netty中buffer的问题,自己回答的不太好,嗯,该看的还是要看的。。。。

fjs的专栏 6810

Netty 内存模型分析(一)ByteBuf总览

本文开始,将主要围绕netty相关知识展开,力求从宏观上把握整个内存结构。 ByteBuf 为了解决NIO 中 ByteBuffer 使用不当问题,例如读模式写模式不能同时进行,无法自动扩容等。Netty 新建了一种字节容器ByteBuf。 在 ByteBuf 中,定义有 readerIndex,writerIndex 和 capacity 。 内部组织结构如下: 即可读区域、可写,以及容量。 对于 ByteBuf 更好的理解是一个接口(虽然是抽象类),因为里面大部分方法都是abstract。 Abstr

anLA_的专栏 600

Netty之内存分配器ByteBufAllocator

目录 内存分配器继承体系 ByteBufAllocator AbstractByteBufAllocator UnpooledByteBufAllocator newHeapBuffer newDirectBuffer PooledByteBufAllocator PoolThreadLocalCache PoolArena arena分配内存流程 内存分配器继承体系 ...

学无止境 2335

Netty源码之ByteBuf(4.1.44)

Netty源码之ByteBuf(4.1.44) Netty 抛弃了 Java NIO 的 ByteBuffer,因为它功能有限且使用过于复杂。于是乎,Netty 自己弄出了一个类似 ByteBuffer 的数据容器,称之为 ByteBuf,并且提供很多非常酷的特性: 容量可按需动态扩展。 读写采用不同的指针,并随意切换,不需要用户额外调用 flip() 切换读写模式。 通过内置的复合缓冲类型实现零拷贝技术。 支持引用计数。 支持缓存池。 类型丰富,支持堆外内存和堆内内存。 继承关系图 图中所框选的是在

ClarenceZero的博客 685

netty源码分析系列——ByteBuf&UnpooledByteBuf

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34055787的博客 831

Netty零拷贝机制

ByteBuf PooledByteBuf对象、内存复用 零拷贝机制 1 ByteBuf ByteBuf操作 ByteBuf动态扩容 选择合适的ByteBuf实现 1.1 ByteBuf操作 ByteBuf三个重要属性:capacity容量、readerIndex读取位置、writerIndex写入位置。提供了两个指针变量来支持顺序读和写操作,分别是读操作readerIndex和写操作w...

yygEwing的博客 340

初识内存分配ByteBuf

初识ByteBuf:   ByteBuf 是Netty 整个结构里面最为底层的模块,主要负责把数据从底层IO 里面读到ByteBuf,然后传递给应用程序,应用程序处理完成之后再把数据封装成ByteBuf 写回到IO。所以,ByteBuf 是直接与底层打交道的一层抽象。这块内容,相对于Netty 其他模块来说,是非常复杂的。从不同角度来分析ByteBuf 的分配和回收。主要从内存与内存管...

weixin_30908941的博客 195

【Netty专题】源码剖析netty核心基础ByteBuf

在面试的时候,当面试问到netty的时候问到:你知道jdk nio中的ByteBuffer与netty中的ByteBuf有什么区别吗?来看看面试者的基础掌握的如何!你能准确回到出来个所以然吗? 说到jdk我先说说我身边使用jdk nio的情况; 我现在公司就有个游戏项目是jdk nio2一行一行实现的通讯架构,一直在线上运营,目前该架构单服承载最高的时候达到300...

学而不思则罔,思而不学则殆! 557

【Netty源码解读和权威指南】第12篇:Netty ByteBuf全解析(中)—— 堆内、堆外、复合缓冲区,三大模式横评

Netty ByteBuf内存模式深度解析 本文深入剖析Netty ByteBuf的三种内存模式:堆内内存(Heap ByteBuf)、堆外直接内存(Direct ByteBuf)和复合缓冲区(Composite ByteBuf)。通过生产事故案例揭示错误选择内存模式的严重后果,对比分析各类缓冲区的优缺点及适用场景。 核心要点: Heap ByteBuf:分配回收快但I/O需额外复制,适合业务计算和小消息处理 Direct ByteBuf:零拷贝优势明显,适合网络I/O和大数据传输,但需注意内存管理 Com

xyghehehehe的专栏 350
上一篇: (一) netty ByteBuf的分配与使用基础
下一篇: (三) netty非池化内存的分配与回收:UnpooledByteBufAllocator
Joel.Wang老王
博客等级 码龄15年 17粉丝 13原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值