当前位置: 首页 > news >正文

netty4报错:io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1

背景:netty执行链中有一串自定义的handler,目前我想要在中间再加上一个pingPonghandler来进行控制帧的处理,从而避免ng的读写超时(客户要求,与他们建立的通道一直连接,不进行断连,从而需要考虑ng的问题);

当我添加如下代码后报错:io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1,ByteBuf 的引用计数refCnt为0;

import io.netty.buffer.Unpooled;  
import io.netty.channel.ChannelHandlerContext;  
import io.netty.channel.SimpleChannelInboundHandler;  
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;  
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;  
import io.netty.handler.codec.http.websocketx.WebSocketFrame;  public class PingPongHandler extends SimpleChannelInboundHandler<WebSocketFrame> {  @Override  protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {  if (frame instanceof PingWebSocketFrame) {  // 接收到PING帧  System.out.println("Received PING frame");  // 发送PONG帧作为响应  ctx.channel().writeAndFlush(new PongWebSocketFrame(Unpooled.buffer(0)));  } else if (frame instanceof PongWebSocketFrame) {  // 接收到PONG帧  System.out.println("Received PONG frame");  } else {  // 其他类型的帧,继续传递给下一个处理器  ctx.fireChannelRead(frame);  }  }  
}

ByteBuf echoMsg = frame.content();

echoMsg.refCnt(); 获取引用计数

解决办法1:(新手不推荐,最好还是使用netty的自动释放逻辑,避免处理不当)

 echoMsg.retain();  //手动进行引用计数加1,并在使用完成之后释放调

解决方法2:关闭SimpleChannelInboundHandler的自动释放(推荐)

package com.iflytek.iptv.websocket;import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;public class PingPongHandler extends SimpleChannelInboundHandler<WebSocketFrame> {// 构造函数中设置autoRelease为falsepublic PingPongHandler() {super(false);}@Overrideprotected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {if (frame instanceof PingWebSocketFrame) {// 接收到PING帧System.out.println("Received PING frame");// 发送PONG帧作为响应ctx.channel().writeAndFlush(new PongWebSocketFrame(Unpooled.buffer(0)));} else if (frame instanceof PongWebSocketFrame) {// 接收到PONG帧System.out.println("Received PONG frame");} else {// 其他类型的帧,继续传递给下一个处理器ctx.fireChannelRead(frame);}}
}

解决方法3:继承ChannelInboundHandlerAdapter ,默认不释放(推荐)

package com.iflytek.iptv.websocket;import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class PingPongHandler extends ChannelInboundHandlerAdapter {private static final Logger log = LoggerFactory.getLogger(PingPongHandler1.class);@Overridepublic void channelRead(ChannelHandlerContext ctx, Object frame) throws Exception {if (frame instanceof PingWebSocketFrame) {// 接收到PING帧log.info("Received ping frame, connection is alive");// 发送PONG帧作为响应
//            ctx.channel().writeAndFlush(new PongWebSocketFrame(Unpooled.buffer(0)));} else if (frame instanceof PongWebSocketFrame) {// 接收到PONG帧log.info("Received pong frame, connection is alive");} else {// 其他类型的帧,继续传递给下一个处理ctx.fireChannelRead(frame);}}
}

问题分析:

在Netty中,ByteBuf 是一个字节容器,它支持多种数据读写操作,并且其内部使用引用计数(refCnt)来管理资源的生命周期。引用计数用于确保资源(如内存)在不再需要时能够被适当释放,防止内存泄漏。

当你提到继承 SimpleChannelInboundHandler<WebSocketFrame> 和 ChannelInboundHandlerAdapter 并使用 ctx.fireChannelRead(frame) 时,ByteBuf 的引用计数表现不同,这主要是由于 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 处理 ByteBuf 的方式有所区别。

SimpleChannelInboundHandler

SimpleChannelInboundHandler<T> 是一个方便的类,它专门为处理特定类型的入站消息而设计。它会在消息传递到下一个 ChannelHandler 之前自动释放(release())传入的消息对象(如果消息实现了 ReferenceCounted 接口,如 ByteBuf)。这是因为它假设在 channelRead0(ChannelHandlerContext ctx, T msg) 方法中处理完消息后,当前处理器不需要再保留对该消息的引用。

因此,当你在 SimpleChannelInboundHandler 的 channelRead0 方法中调用 ctx.fireChannelRead(frame)(这里的 frame 是 WebSocketFrame 的一个实例,而 WebSocketFrame 内部通常包含 ByteBuf),由于 SimpleChannelInboundHandler 的设计,Netty 会在将消息传递给下一个处理器之前自动调用 release()。这就是为什么你看到引用计数减少的原因。

ChannelInboundHandlerAdapter

相反,ChannelInboundHandlerAdapter 是一个更通用的基类,它不假设你会在方法执行后立即释放消息。因此,当你在 ChannelInboundHandlerAdapter 的 channelRead 方法中调用 ctx.fireChannelRead(frame) 时,Netty 不会自动调用 release()。这意呀着你需要自己管理 ByteBuf 的生命周期,确保在不再需要时调用 release(),否则可能导致内存泄漏。

应该选择哪个?

  • 如果你处理的是实现了 ReferenceCounted 接口的对象(如 ByteBuf),并且你的处理器在处理完消息后不再需要它,那么 SimpleChannelInboundHandler 是一个不错的选择,因为它可以自动管理引用计数。
  • 如果你需要更细粒度的控制,比如你计划在多个处理器之间共享 ByteBuf,或者你的处理器只是将消息传递给下一个处理器而不立即处理它,那么 ChannelInboundHandlerAdapter 可能是更好的选择。但是,你需要确保自己正确地管理引用计数,避免内存泄漏。

结论

       不是所有的中间处理器都必须继承 ChannelInboundHandlerAdapter。如果你处理的消息类型是特定的,并且你可以接受 SimpleChannelInboundHandler 的自动释放行为,那么使用它可能更方便。然而,如果你需要更复杂的处理逻辑或消息共享,那么 ChannelInboundHandlerAdapter 将提供更多的灵活性。重要的是要根据你的具体需求来选择适当的处理器类。

相关文章:

netty4报错:io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1

背景&#xff1a;netty执行链中有一串自定义的handler&#xff0c;目前我想要在中间再加上一个pingPonghandler来进行控制帧的处理&#xff0c;从而避免ng的读写超时&#xff08;客户要求&#xff0c;与他们建立的通道一直连接&#xff0c;不进行断连&#xff0c;从而需要考虑n…...

2022年汽车软件行业产业细分及发展趋势分析

2022年汽车软件行业产业细分及发展趋势分析 连接 2022年汽车软件行业产业细分及发展趋势分析...

如何通过变更让 PostgreSQL 翻车

在开发应用程序和维护其后台数据库集群的过程中&#xff0c;我们经常会遇到实践与理论、开发环境与生产环境之间的差异。其中一个典型的例子就是变更数据库中的列类型。 对于在 PostgreSQL&#xff08;及其他符合 SQL 标准的系统&#xff09;中变更列类型的常规操作&#xff0…...

MySQL表涉及规范

MySQL表设计规范是为了确保数据库表结构的合理性、可读性和可维护性。以下是一些建议和规范&#xff1a; 1.使用InnoDB存储引擎&#xff1a;InnoDB存储引擎提供了事务支持、行级锁定和外键约束&#xff0c;有助于提高数据的完整性和性能。 2.表名和字段名命名规范&#xff1a…...

服务器Ubuntu22.04系统 使用dcocker部署安装ollama和搭配open_webui使用

服务器Ubuntu22.04系统 使用dcocker部署安装ollama和搭配open_webui使用 一、ubuntu和docker基本环境配置 1.更新包列表&#xff1a; 打开终端&#xff0c;输入以下命令&#xff1a; sudo apt-get updatesudo apt upgrade更新时间较长&#xff0c;请耐心等待 2. 安装docke…...

代理模式Proxy

一、代理模式&#xff08;Proxy&#xff09; 1.代理模式的定义 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对真实对象的访问&#xff0c;起到对代理对象已有功能的增强 通俗的来讲代理模式就是我们生活中常见的中介。 2.作用 中介隔离作用&#x…...

C++ 设计模式——抽象工厂模式

抽象工厂模式 抽象工厂模式 抽象工厂模式主要组成部分代码实现抽象工厂模式模式的 UML 图抽象工厂模式 UML 图解析优点和缺点适用场景 抽象工厂模式提供一个接口&#xff0c;用于创建一系列相关或相互依赖的对象&#xff0c;而无需指定它们的具体类。它通常用于需要创建多个产品…...

《亿级流量系统架构设计与实战》第十一章 Timeline Feed服务

Timeline Feed服务 一、概述1、分类2、功能 二、设计原理1、拉模式与用户发件箱2、推模式与用户收件箱3、推拉模式结合 三、关键技术1、内容与用户收件箱的交互&#xff08;推模式&#xff09;2、推送拆分子任务3、收件箱模型设计 内容总结自《亿级流量系统架构设计与实战》 一…...

氙灯老化试验箱试验机

氙灯老化试验箱&#xff0c;采用6.5KW大功率的精密水冷式氙灯&#xff0c;曝晒面积达到了6500cm2 功能强大&#xff0c;测试结果可靠 ◆ 满足国内外所有氙灯测试标准要求。 ◆ 采用氙灯灯管及滤光器组件&#xff0c;保证试验数据的可比性和重现性。 ◆ 自动旋转式三层鼓型样板架…...

【Qt】常用控件QRadioButton

常用控件QRadioButton QRadioButton是单选按钮&#xff0c;可以在多个选项中选择一个。 作为QAbstractButton和QWidget的子类&#xff0c;其属性和用法&#xff0c;对于QRadioButton同样适用。 属性说明 checkable 是否能选中 checked 是否已经被选中. checkable 是 checked…...

Mysql 离线版下载安装-(详细版)

Mysql 离线版下载安装-(详细版) 文章目录 Mysql 离线版下载安装-(详细版)1.0 下载地址2.0 解压到本地2.0.1 配置环境变量2.0.2 新建mysql配置文件ini2.0.3使用管理员启动 cmd 3.0 初始化密码忘记了4.0 修改初始化密码5.0 使用可视化工具登录Mysql 1.0 下载地址 地址&#xff1…...

Spring Boot和OCR构建车牌识别系统

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 OCR介绍 OCR&#xff08;Optical Character Recognition&#xff09;是光学字符识别技术的缩写&#xff0c;它能够将图像中的文本转换为机器可读和编辑的数字文本格式。这种技术广泛应用于数据输入、文档管理…...

Java-自定义注解中成员变量是Class<?>

在Java中,自定义注解可以包含各种类型的成员变量,包括 Class<?> 类型。这种类型的成员变量 通常用于表示某个类的类型信息。下面我将详细介绍如何定义一个包含 Class<?> 类型成员变量的 自定义注解,并给出一些示例代码。 1. 定义自定义注解 定义一个自定义…...

SX_UNIX套接字通信_15

UNIX套接字通信的优势&#xff1a; UNIX套接字通信常用于一个项目中的进程之间通信&#xff0c;UNIX提供了与网络套接字相似的特性&#xff0c;但是避免了网络延迟&#xff0c;提高了性能&#xff0c;但是它只能在同一台机器上使用&#xff0c;无法跨越网络的进程间通信 实例&…...

JS模块化总结 | CommonJS、ES6

BV13W42197jR 个人笔记 目录 JS模块化基础知识1. 概述1.1 什么是模块化1.2 为什么需要模块化? 2 模块化规范3 导入&导出4 CommonJS规范4.1 初步体验4.2 导出数据4.3 导入数据4.4 扩展理解4.5 浏览器端运行 5 ES6模块化规范5.1 初步体验5.2 Node中运行ES65.3 导出数据①分别…...

25考研计算机组成原理复习·3.5高速缓冲存储器

高速缓冲存储器Cache 工作原理&#xff1a;将某些主存块复制到Cache中&#xff0c;缓和CPU与主存之间的速度矛盾局部性原理 时间局部性&#xff1a;现在访问的地址&#xff0c;不久之后也很可能被再次访问空间局部性&#xff1a;现在访问的地址&#xff0c;其附近的地址也很可…...

餐厅管理系统

目录 一、 系统简介 1.1需求分析 1.2 编程环境与工具 二、 系统总体设计 2.1 系统的功能模块图。 2.2 各功能模块简介。 三、 主要业务流程 &#xff08;1&#xff09;用户及管理员登录流程图 &#xff08;2&#xff09;信息添加流程 &#xff08;3&#xf…...

杭州百腾教育科技 TiDB 6.5 to 7.5 升级记录

作者&#xff1a; reAsOn2010 原文来源&#xff1a; https://tidb.net/blog/612103f3 背景 使用 TiDB 作为我们的全量数据库已经有六七年了&#xff0c;当时还是 2.0 版本。早期TiDB的迭代和新特性的发布对于实际使用的影响还是很大的&#xff0c;所以从那个时候开始就有每…...

Redis的缓存穿透、击穿、雪崩

目录 缓存穿透 定义&#xff1a; 解决方法&#xff1a; 缓存击穿 定义&#xff1a; 解决方案&#xff1a; 缓存雪崩 定义&#xff1a; 解决方案&#xff1a; 缓存穿透、缓存击穿和缓存雪崩的区别 缓存穿透 定义&#xff1a; 查询一个不存在的数据&#xff0c;数据库未…...

【Django开发】前后端分离django美多商城项目第1篇:欢迎来到美多 项目主要页面介绍【附代码文档】

本教程的知识点为&#xff1a; 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计&#xff1a; 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...

Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程

鸿蒙电脑版操作系统来了&#xff0c;很多小伙伴想体验鸿蒙电脑版操作系统&#xff0c;可惜&#xff0c;鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机&#xff0c;来体验大家心心念念的鸿蒙系统啦&#xff01;注意&#xff1a;虚拟…...