Netty:ByteBuf的资源释放方法

说明

io.netty.buffer.ByteBuf实现了io.netty.util.ReferenceCounted接口,需要显式释放。当ByteBuf被实例化后,它的引用计数是1。

调用ByteBuf对象的release方法释放:

  • ByteBuf的release()方法使引用计数减少1。只有当执行以后引用计数减少到0,该函数才返回true。当ByteBuf的引用计数减少到0时,ByteBuf会被释放。
  • 当ByteBuf的引用计数是0时,再执行release()方法会抛出IllegalReferenceCountException异常。

调用ReferenceCountUtil的方法释放:

  • release(Object msg):如果要被释放的对象msg实现了ReferenceCounted接口,那么内部会调用该对象的release()方法,并返回执行release()方法的结果。如果要被释放的对象msg没有实现ReferenceCounted接口,那么直接返回false。
  • safeRelease(Object msg):当要被释放的对象实现了ReferenceCounted接口,内部调用对象的release()方法来释放;如果对象的当前引用计数是0时,如果执行该函数,不会抛出异常,而是打印告警日志。如果要被释放的对象没有实现ReferenceCounted接口,执行该函数不会有任何作用。

代码示例

执行ByteBuf的release()返回结果观察

package com.thb;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;public class Demo {public static void main(String[] args) {// 创建一个ByteBufByteBuf buf = Unpooled.buffer();// 引用计数加1buf.retain();// 此时的引用计数是2System.out.println("buf.refCnt: " + buf.refCnt());// 此时执行buf.release()返回false,因为执行以后的引用计数变成1System.out.println("buf.release: " + buf.release());// 此时的引用计数是1System.out.println("buf.refCnt: " + buf.refCnt());System.out.println("buf.release: " + buf.release());// 此时执行buf.release()返回true,因为执行以后的引用计数变成0System.out.println("buf.refCnt: " + buf.refCnt());		}}

运行输出:

buf.refCnt: 2
buf.release: false
buf.refCnt: 1
buf.release: true
buf.refCnt: 0

ByteBuf的引用计数是0时,再执行release()方法会抛出IllegalReferenceCountException异常

package com.thb;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;public class Demo {public static void main(String[] args) {// 创建一个ByteBufByteBuf buf = Unpooled.buffer();// 此时的引用计数是1System.out.println("buf.refCnt: " + buf.refCnt());// 此时执行buf.release()返回true,因为执行以后的引用计数变成0System.out.println("buf.release: " + buf.release());// 此时的引用计数是0System.out.println("buf.refCnt: " + buf.refCnt());// ByteBuf的引用计数已经变成0,再执行release()函数会抛出IllegalReferenceCountException异常System.out.println("buf.release: " + buf.release());}}

运行结果:

buf.refCnt: 1
buf.release: true
buf.refCnt: 0
Exception in thread "main" io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:83)at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:148)at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101)at com.thb.Demo.main(Demo.java:19)

调用ReferenceCountUtil的release(Object msg)方法释放

package com.thb;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;public class Demo {public static void main(String[] args) {// 创建一个ByteBufByteBuf buf = Unpooled.buffer();// 此时的引用计数是1System.out.println("buf.refCnt: " + buf.refCnt());// 此时执行ReferenceCountUtil.release(buf)返回true,因为执行以后的引用计数变成0System.out.println("ReferenceCountUtil.release: " + ReferenceCountUtil.release(buf));// 此时的引用计数是0System.out.println("buf.refCnt: " + buf.refCnt());}}

运行输出:

buf.refCnt: 1
ReferenceCountUtil.release: true
buf.refCnt: 0

用ReferenceCountUtil的release(Object msg)释放一个引用计数为0的对象,抛出异常

package com.thb;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;public class Demo {public static void main(String[] args) {// 创建一个ByteBufByteBuf buf = Unpooled.buffer();// 此时的引用计数是1System.out.println("buf.refCnt: " + buf.refCnt());// 此时返回true,因为执行以后的引用计数变成0System.out.println("ReferenceCountUtil.release: " + ReferenceCountUtil.release(buf));// 此时的引用计数是0System.out.println("buf.refCnt: " + buf.refCnt());// 抛出异常,因为在执行调用前,buf当前的引用计数已经是0了System.out.println("ReferenceCountUtil.release: " + ReferenceCountUtil.release(buf));}}

运行输出:

buf.refCnt: 1
Exception in thread "main" io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:83)at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:148)at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101)at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:90)at com.thb.Demo.main(Demo.java:21)
ReferenceCountUtil.release: true
buf.refCnt: 0

调用ReferenceCountUtil的release(Object msg)方法释放一个没有实现ReferenceCounted接口的对象,结果为false

package com.thb;import io.netty.util.ReferenceCountUtil;public class Demo {public static void main(String[] args) {String msg = "hello";// 此时返回false,因为对象是String类型,没有实现ReferenceCounted接口System.out.println("ReferenceCountUtil.release: " + ReferenceCountUtil.release(msg));}}

运行输出:
在这里插入图片描述

调用ReferenceCountUtil的safeRelease(Object msg)方法释放实现了ReferenceCounted接口的对象;如果对象当前引用计数为0,打印告警日志

package com.thb;import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;public class Demo {public static void main(String[] args) {// 创建一个ByteBufByteBuf buf = Unpooled.buffer();// 此时的引用计数是1System.out.println("buf.refCnt: " + buf.refCnt());// 正常释放ReferenceCountUtil.safeRelease(buf);		// 此时的引用计数是0System.out.println("buf.refCnt: " + buf.refCnt());// buf的引用计数已经在0了,再释放会打印告警日志ReferenceCountUtil.safeRelease(buf);}}

运行输出:

buf.refCnt: 1
buf.refCnt: 0
14:55:40.222 [main] WARN  io.netty.util.ReferenceCountUtil - Failed to release a message: UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(freed)
io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1at io.netty.util.internal.ReferenceCountUpdater.toLiveRealRefCnt(ReferenceCountUpdater.java:83) ~[classes/:?]at io.netty.util.internal.ReferenceCountUpdater.release(ReferenceCountUpdater.java:148) ~[classes/:?]at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101) ~[classes/:?]at io.netty.util.ReferenceCountUtil.release(ReferenceCountUtil.java:90) ~[classes/:?]at io.netty.util.ReferenceCountUtil.safeRelease(ReferenceCountUtil.java:116) [classes/:?]at com.thb.Demo.main(Demo.java:20) [classes/:?]

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

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

相关文章

C++ 混合Python编程 及 Visual Studio配置

文章目录 需求配置环节明确安装的是64位Python安装目录 创建Console C ProjectCpp 调用 Python Demo 参考 需求 接手了一个C应用程序,解析csv和生成csv文件,但是如果要把多个csv文件合并成一个Excel,分布在不同的Sheet中,又想在一…

vue基础知识四:Vue实例挂载的过程

一、思考 我们都听过知其然知其所以然这句话 那么不知道大家是否思考过new Vue()这个过程中究竟做了些什么? 过程中是如何完成数据的绑定,又是如何将数据渲染到视图的等等 一、分析 首先找到vue的构造函数 源码位置:src\core\instance\…

最新版本的Anaconda环境配置、Cuda、cuDNN以及pytorch环境一键式配置流程

本教程是最新的深度学习入门环境配置教程,跟着本教程可以帮你解决入门深度学习之前的环境配置问题。同时,本教程拒绝琐碎,大部分以图例形式进行教程。这里我们安装的都是最新版本~ 文章目录 一、Anaconda的安装1.1 下载1.2 安装1.3 环境配置…

【Vue3 博物馆管理系统】使用Vue3、Element-plus菜单组件构建前台用户菜单

系列文章目录 第一章 定制上中下(顶部菜单、底部区域、中间主区域显示)三层结构首页 第二章 使用Vue3、Element-plus菜单组件构建菜单 [第三章 使用Vue3、Element-plus菜单组件构建轮播图] [第四章 使用Vue3、Element-plus菜单组件构建组图文章] 文章目…

数据结构--有向⽆环图 描述表达式

数据结构–有向⽆环图 描述表达式 有向⽆环图 \color{red}有向⽆环图 有向⽆环图:若⼀个有向图中 不存在环 \color{red}不存在环 不存在环,则称为有向⽆环图,简称 D A G 图 \color{red}DAG图 DAG图(Directed Acyclic Graph&#x…

Prim+Kruskal(最小生成树)

Prim算法求最小生成树 给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环,边权可能为负数。 求最小生成树的树边权重之和,如果最小生成树不存在则输出 impossible。 给定一张边带权的无向图 G(V,E),其中 V 表示图中点的集…

【BERTopic应用 03/3】:微调参数

一、说明 一般来说,BERTopic 在开箱即用的模型中工作得很好。但是,当您有数百万个数据要处理时,使用基本模型处理数据可能需要一些时间。在这篇文章中,我将向您展示如何微调BERTopic中的一些参数并比较它们的结果。让我们潜入。 二…

Qt扫盲-QTableView理论总结

QTableView理论总结 一、概述二、导航三、视觉外观四、坐标系统五、示例代码1. 性别代理2. 学生信息模型3. 对应视图 一、概述 QTableView实现了一个tableview 来显示model 中的元素。这个类用于提供之前由QTable类提供的标准表,但这个是使用Qt的model/view架构提供…

数据结构(一):顺序表详解

在正式介绍顺序表之前,我们有必要先了解一个名词:线性表。 线性表: 线性表是,具有n个相同特性的数据元素的有限序列。常见的线性表:顺序表、链表、栈、队列、数组、字符串... 线性表在逻辑上是线性结构,但…

opencv进阶01-直方图的应用及示例cv2.calcHist()

直方图是什么? 直方图是一种图形表示方法,用于显示数据中各个数值或数值范围的分布情况。它将数据划分为一系列的区间(也称为“箱子”或“bin”),然后统计每个区间中数据出现的频次(或频率)。直…

力扣初级算法(数组拆分)

力扣初级算法(数组拆分) 每日一算法: 力扣初级算法(数组拆分) 学习内容: 1.问题描述 给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) …

pytest自动生成测试类 demo

一、 pytest自动生成测试类 demo # -*- coding:utf-8 -*- # Author: 喵酱 # time: 2023 - 08 -15 # File: test4.py # desc: import pytest import unittest# 动态生成测试类def create_test_class(class_name:str, test_cases:list) -> type:"""生成测试类…

流程挖掘in汽车丨宝马的流程效能提升实例

汽车行业在未来10年里,可能会面临比过去50年更多的变化。电动化、智能化、共享化和自动驾驶等方面的趋势可能给企业流程带来以下挑战: 供应链管理-电动化和智能化的发展可能导致供应链中的零部件和系统结构发生变化,企业需要重新评估和优化供…

结构体指针变量的使用

1、结构体指针的引用 #include<iostream> using namespace std;struct Student {int num;char name[32]; }; int main() {struct Student stu {1,"张三"};struct Student* p &stu;system("pause"); return 0; } 2、通过结构体指针访问结构体…

vue所有UI库通用)tree-select 下拉多选(设置 maxTagPlaceholder 隐藏 tag 时显示的内容,支持鼠标悬浮展示更多

如果可以实现记得点赞分享&#xff0c;谢谢老铁&#xff5e; 1.需求描述 引用的下拉树形结构支持多选&#xff0c;限制选中tag的个数&#xff0c;且超过制定个数&#xff0c;鼠标悬浮展示更多已选中。 2.先看下效果图 3.实现思路 首先根据API文档&#xff0c;先设置maxTagC…

嵌入式 C 语言程序数据基本存储结构

一、5大内存分区 内存分成5个区&#xff0c;它们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 1、栈区(stack)&#xff1a;FIFO就是那些由编译器在需要的时候分配&#xff0c;在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。 ​…

什么是层叠上下文(stacking context)?它是如何形成的?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 层叠上下文&#xff08;Stacking Context&#xff09;是什么&#xff1f;⭐ 层叠上下文的形成⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎…

Vue2(组件开发)

目录 前言一&#xff0c;组件的使用二&#xff0c;插槽slot三&#xff0c;refs和parent四&#xff0c;父子组件间的通信4.1&#xff0c;父传子 &#xff1a;父传子的时候&#xff0c;通过属性传递4.2&#xff0c;父组件监听自定义事件 五&#xff0c;非父子组件的通信六&#x…

网络安全攻防实战:探索互联网发展史

大家好&#xff0c;我是沐尘而生。 互联网发展史&#xff1a;数字世界的壮阔画卷 从早期的ARPANET到今天的万物互联&#xff0c;互联网经历了漫长的发展过程。然而&#xff0c;随着技术的进步&#xff0c;网络安全问题也随之而来。我们不仅要探索互联网的壮阔历程&#xff0c;…

浅谈 EMP-SSL + 代码解读:自监督对比学习的一种极简主义风

论文链接&#xff1a;https://arxiv.org/pdf/2304.03977.pdf 代码&#xff1a;https://github.com/tsb0601/EMP-SSL 其他学习链接&#xff1a;突破自监督学习效率极限&#xff01;马毅、LeCun联合发布EMP-SSL&#xff1a;无需花哨trick&#xff0c;30个epoch即可实现SOTA 主要…