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 视图使用规则: …

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

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

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…

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

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

无人机之产业链篇

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

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

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

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

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

【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文件的所有图片 然后勾选优先使用相…

monocle3拟时序分析怎么做到多样本间pseudotime值可比?

愿武艺晴小朋友一定得每天都开心 monocle3呢,有好多文章分享了它的流程。跟着学呢,也都能计算出一套pseudotime值。 在跑monocle3时,我就有一个困惑产生了:monocle3计算的pseudotime值在多样本间可比,该怎么做到呀&am…

学习大数据DAY20 Linux环境配置与Linux基本指令

目录 Linux 介绍 Linux 发行版 Linux 和 Windows 比较 Linux 就业方向: 下载 CentOS Linux 目录树 Linux 目录结构 作业 1 常用命令分类 文件目录类 作业 2 vim 编辑文件 作业 3 你问我第 19 天去哪了?第 19 天在汇报第一阶段的知识总结,没什…

QT5:多窗口跳转

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助 目录 前言 一、环境 二、步骤 三、代码实现 四、效果图 前言 学习使用qt5完成多窗口(界面)跳转:从主界面可分别跳转至界面一和界面二&#xf…

Spring Boot集成SFTP快速入门Demo

1.什么是SFTP? SFTP(SSH File Transfer Protocol,也称 Secret File Transfer Protocol),是一种基于SSH(安全外壳)的安全的文件传输协议。使用SFTP协议可以在文件传输过程中提供一种安全的加密算…

主从复制 哨兵服务 数据类型 持久化

配置主从复制 一主多从结构 配置一主一从结构 修改配置文件 配置salve服务器 配置带验证的主从复制 查看密码,默认redis服务没有密码 192.168.88.61:6379> config get requirepass 设置密码 192.168.88.61:6379> config set requirepass 123456 输入密码…

Spring Boot2(Spring Boot 的Web开发 springMVC 请求处理 参数绑定 常用注解 数据传递)

目录 一、Spring Boot 的Web开发 1. 静态资源映射规则 2. enjoy模板引擎 二、springMVC 1. springMVC-请求处理 测试: 以post方式请求 限制请求携带的参数 GetMapping 查询 PostMapping 新增 DeleteMapping删除 PutMapping 修改 2. springMVC-参…

HarmonyOS鸿蒙- 跳转系统应用能力

一、通过弹窗点击设置跳转系统应用能力 1、 自定义弹窗效果图 2、 自定义弹窗代码 import { common, Want } from kit.AbilityKit; import { BusinessError } from kit.BasicServicesKit;export function alertDialog() {AlertDialog.show({title: ,message: 当前功能依赖定位…

ranger审计日志对接CDH solr

作者:耀灵 一、准备条件 1、已安装完毕ranger-admin 2、已在CDH上部署solr(注意在安装solr时更改下solr在zk上的节点信息) 二、更改相关配置 1、修改ranger-2.1.0-admin/contrib/solr_for_audit_setup/install.properties SOLR_USERsolr …