ByteBuf释放注意的问题

Bytebuf需要释放,否则可能导致OOM。
如果bytebbuf传递到了head或tail,不需要我们关心。
在head和tail里(head实现了outhandler、inhander。tail实现了inhander),底层自动调用了bytebuf.release。
其他情况需要我们手动释放。 注意simpleinboundHandler特殊
在这里插入图片描述

netty默认使用的直接内存(也叫非堆内存),它创建、销毁的开销同比堆内存大,所以用池化来复用。池化也能用在堆内存上,所以一共有四种:池化直接内存、池化堆内存、非池化直接内存、非池化堆内存。

会自动扩容,可扩容部分就是下图紫色。
byteBuf的结构

创建ByteBuf

        ByteBuf poolHeapBuf = ByteBufAllocator.DEFAULT.heapBuffer();ByteBuf poolDiredtBuf = ByteBufAllocator.DEFAULT.directBuffer();ByteBuf unpoolHeapBuf = Unpooled.buffer();ByteBuf unpoolDirBuf = Unpooled.directBuffer();System.out.println(poolHeapBuf);System.out.println(poolDiredtBuf);System.out.println(unpoolHeapBuf);System.out.println(unpoolDirBuf);

前两种是否是池化,需要看-Dio.netty.allocator.type=unpooled|pooled,如果是pooled,则二者都是池化内存。
后两种一定是非池化内存。
参数为pooled时,输出如下。实际中,还可以用ChannelHandlerContext ctx来分配。

PooledUnsafeHeapByteBuf(ridx: 0, widx: 0, cap: 256)
PooledUnsafeDirectByteBuf(ridx: 0, widx: 0, cap: 256)
UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 0, widx: 0, cap: 256)
UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf(ridx: 0, widx: 0, cap: 256)

netty原码释放逻辑

当多个handler串起来时,数据会沿着链传统。用inboundhandler举例。
如何唤起下一个inhandler呢?可以调用fireChannelRead

class ServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ctx.fireChannelRead(msg);}
}

底层就是:

    @Overridepublic ChannelHandlerContext fireChannelRead(final Object msg) {invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);return this;}

findContextInbound就是找到下一个handler。
invokeChannelRead就是调用下一个handler的invokeChannelRead,代码如下。
始终让Niothread去执行invokeChannelRead。并且执行的最后一个肯定是tail。

    static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);EventExecutor executor = next.executor(); // 该context所属的线程if (executor.inEventLoop()) {next.invokeChannelRead(m);} else {executor.execute(new Runnable() {@Overridepublic void run() {next.invokeChannelRead(m);}});}}

然后执行tail里面的代码
尤其是看看注释是啥:用户在channelRead里面没有处理message 并且该message传递到了tail节点,那么tail节点就会负责释放内存。

    /*** Called once a message hit the end of the {@link ChannelPipeline} without been handled by the user* in {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)}. This method is responsible* to call {@link ReferenceCountUtil#release(Object)} on the given msg at some point.*/protected void onUnhandledInboundMessage(Object msg) {try {logger.debug("Discarded inbound message {} that reached at the tail of the pipeline. " +"Please check your pipeline configuration.", msg);} finally {ReferenceCountUtil.release(msg);}}

为什么始终让Niothread去执行invokeChannelRead?
假如我们这样做,Netty还是会交给NIO线程去释放。

 new Thread(() -> {ctx.fireChannelRead(msg);}).start();

Netty 中的 invokeChannelRead 方法必须在 NIO 线程池中执行,以确保网络读事件的处理是高效、可靠和非阻塞的。

simpleinboundHandler

他为什么特殊?他在自己的finally快里面就释放了

    @Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {boolean release = true;try {if (acceptInboundMessage(msg)) {@SuppressWarnings("unchecked")I imsg = (I) msg;channelRead0(ctx, imsg);} else {release = false;ctx.fireChannelRead(msg);}} finally {if (autoRelease && release) {ReferenceCountUtil.release(msg);}}}

所以如果实现了sampleinboundhandler,byteBuf不用手动释放,也不用传递到tail去。

手动释放

调用release()方法即可。
有特别注意的点。
ByteBuf的一些方法如slice()、duplicate、compositeByteBuf等,都是基于原数组的引用。
如果你释放掉了,其他人持有该引用写入就会发生问题。
最好是每调用上述方法一次,就引用次数+1retain(),谁使用完,谁就release掉。

    public static void main(String[] args) throws Exception {ByteBuf poolHeapBuf = ByteBufAllocator.DEFAULT.heapBuffer(10);// 模拟多人使用use(poolHeapBuf);use(poolHeapBuf);}private static void use(ByteBuf poolHeapBuf) {ByteBuf slice = poolHeapBuf.slice(0, 3);slice.retain();// 执行逻辑完,最后释放掉。slice.release();}

本文作者:WKP9418
本文地址:https://blog.csdn.net/qq_43179428/article/details/140564408

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

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

相关文章

MySQL(终章)视图, 用户管理, C连接MySQL.

目录 1.视图; 2.用户管理; 1.视图: 1.1 概念和基本操作: 视图本质就是表结构, 虚拟表. 视图和基表数据的改变都会相互影响. 创建视图语法: create view 视图名 as select语句; 修改视图: update set ; 删除视图: drop view 视图名; 1. 2 视图使用规则: …

集成学习的艺术:使用Scikit-Learn实现模型融合

集成学习的艺术:使用Scikit-Learn实现模型融合 在机器学习领域,集成学习是一种强大的技术,它通过结合多个模型的预测来提高整体性能。Scikit-Learn(简称sklearn),作为Python中最受欢迎的机器学习库之一&am…

IP地址:由电脑还是网线决定?

IP地址:由电脑还是网线决定? 在互联网时代,IP地址是我们进行网络通信的基础。然而,对于IP地址究竟是由电脑决定还是由网线决定的问题,不少人可能存在疑惑。本文将从IP地址的定义、分配方式以及影响因素等方面进行探讨…

减分兔搜题-12123学法减分20题目及答案 #媒体#职场发展

对于即将参加驾驶考试的朋友来说,掌握一些经典题目和答案至关重要。今天,我就为大家带来了这样一份干货——20道驾驶考试题目和答案,助你轻松应对考试!这些题目不仅包括了考试中常考的内容,还有针对难点和重点的详细解…

时序数据库-02-聊一聊时序数据库

时序数据库系列 时序数据库-01-时序数据库有哪些?为什么要使用 时序数据库-02-聊一聊时序数据库 时序数据库-03-pentsdb-分布式时序数据库 时序数据库-04-InfluxData-分布式时序数据库 时序数据库-05-TDengine 是一款开源、高性能、云原生的时序数据库 (Time-S…

ETL数据同步之DataX,附赠一套DataX通用模板

今天跟大家分享数据同步datax的模板,小伙伴们简单直接借鉴使用。 还记得上一篇关于大数据DS调度工具的分享嘛? 主流大数据调度工具DolphinScheduler之数据ETL流程-CSDN博客 里面的核心就是采用了DATAX的数据同步原理。 一,什么是DataX D…

基于luckysheet实现在线电子表格和Excel在线预览

概述 本文基于luckysheet实现在线的电子表格,并基于luckyexcel实现excel文件的导入和在线预览。 效果 实现 1. luckysheet介绍 Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。 官方文档在线Demo 2. 实现 …

华为云.VPC关联概念与对等连接实践

云计算.华为云 VPC关联概念与对等连接实践 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/q…

AWS全服务历史年表:发布日期、GA和服务概述一览(一)

我一直在尝试从各种角度撰写关于Amazon Web Services(AWS)的信息和魅力。由于我喜欢技术历史,这次我总结了AWS服务发布的历史年表。 虽然AWS官方也通过“Whats New”发布了官方公告,但我一直希望能有一篇文章将公告日期、GA日期&…

Java流的奥秘:字节与字符的交响乐章

在Java编程的广阔天地中,数据的流动如同一条条看不见的河流,滋养着程序的生命力。而流(Stream)作为数据传输的核心机制,承载着数据的读写重任。今天,我们将深入探讨字节流与字符流的精妙之处,解锁它们背后的编程艺术。…

视频监控平台LntonCVS视频融合共享平台智慧安防视频监控汇聚应用方案

LntonCVS是一款功能强大且灵活部署的安防视频监控平台。它支持多种主流标准协议,包括GB28181、RTSP/Onvif、RTMP等,同时能够兼容海康Ehome、海大宇等厂家的私有协议和SDK接入。该平台不仅提供传统的安防监控功能,还支持接入AI智能分析&#x…

无人机之产业链篇

无人机产业链上游为无人机设计研发及关键原材料的生产,其中关键原材料有金属材料和复合材料两大类,包括钛合金、铝合金、陶瓷基等特殊材料 中游无人机整机制造包括飞行系统、地面系统、任务载荷系统三个方面,是无人机制造的核心部分&#xf…

Adobe国际认证详解-网页设计认证专家行业应用场景解析

在当今数字化时代,网页设计已成为各行各业不可或缺的一环。而网页设计认证专家,作为经过Adobe国际认证体系严格考核的专业人才,正逐渐成为行业内炙手可热的存在。他们凭借深厚的网页设计理论基础和实践经验,为各行各业提供了高质量…

144. 字典序最小的 01 字符串(卡码网周赛第二十六期(23年阿里淘天笔试真题))

题目链接 144. 字典序最小的 01 字符串(卡码网周赛第二十六期(23年阿里淘天笔试真题)) 题目描述 小红有一个 01 字符串,她可以进行最多 k 次提作,每次操作可以交换相邻的两个字符,问可以得到的…

java设计模式:03-06-享元模式

享元模式(Flyweight Pattern) 享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术来有效地支持大量细粒度对象的重用。享元模式避免了在相似对象间的高开销,通过共享尽可能多的状态来尽量减…

正则表达式:电子邮件地址的格式详解,及常见正则表达式符号的详细解释和匹配方式

一、第一部分是对该段电子邮件的详解 var Regex /^(?:\w\.?)*\w(?:\w\.)*\w$/; 1.^:这个符号表示匹配输入字符串的开始位置。 2.(?:...):这是一个非捕获组(non-capturing group),用于将正则表达式的一部分组合在…

B端产品经理能力培养(四)

B端产品经理能力模型 通用能力 学习能力 沟通能力 行业融入感主人翁精神 心态和情商 专业素养 责任心 自驱力、执行力 基础认知 产品行业认知:当前公司的产品所属细分领域、所处行业趋势、提供怎样的服务、产品和方案解决了客户哪些问题。 产品聚焦领域&a…

【Langchain大语言模型开发教程】模型、提示和解析

🔗 LangChain for LLM Application Development - DeepLearning.AI 学习目标 1、使用Langchain实例化一个LLM的接口 2、 使用Langchain的模板功能,将需要改动的部分抽象成变量,在具体的情况下替换成需要的内容,来达到模板复用效…

【Linux服务器Java环境搭建】012在linux中安装消息队列RabbitMQ,以及对RabbitMQ设置、启动、开启可视化

系列文章目录 【Linux服务器Java环境搭建】 前言 上一篇博客竟然用了不到半小时就写完了,那就继续吧,如果对此系列感兴趣,可以点击系列【Linux服务器Java环境搭建】进行查看哈,这一篇主要是安装和配置消息队列RabbitMQ。 一、消…

[解决方法]git上传的项目markdown文件的图片无法显示

应该有不少初学者会遇到这种情况 以下是本人摸索出的解决方法 我使用的是typora,首先设置typora的图片设置 文件>偏好设置>图像 如下: 选择这个就会在此文件的同级目录下创建一个assets文件夹来存放此markdown文件的所有图片 然后勾选优先使用相…