参考资料:http://www.maljob.com/pages/newsDetail.html?id=394

参考资料:http://www.blogjava.net/liuguly/archive/2014/05/03/413172.html

1.为什么要有引用计数器

Netty里四种主力的ByteBuf,

其中UnpooledHeapByteBuf 底下的byte[]能够依赖JVM GC自然回收;而UnpooledDirectByteBuf底下是DirectByteBuffer,如Java堆外内存扫盲贴所述,除了等JVM GC,最好也能主动进行回收;而PooledHeapByteBuf 和PooledDirectByteBuf,则必须要主动将用完的byte[]/ByteBuffer放回池里,否则内存就要爆掉。所以,Netty ByteBuf需要在JVM的GC机制之外,有自己的引用计数器和回收过程。

2. 引用计数器常识

计数器基于 AtomicIntegerFieldUpdater,为什么不直接用AtomicInteger?因为ByteBuf对象很多,如果都把int包一层AtomicInteger花销较大,而AtomicIntegerFieldUpdater只需要一个全局的静态变量。

所有ByteBuf的引用计数器初始值为1。

调用release(),将计数器减1,等于零时, deallocate()被调用,各种回收。

调用retain(),将计数器加1,即使ByteBuf在别的地方被人release()了,在本Class没喊cut之前,不要把它释放掉。

由duplicate(), slice()和order(ByteOrder)所创建的ByteBuf,与原对象共享底下的buffer,也共享引用计数器,所以它们经常需要调用retain()来显示自己的存在。

当引用计数器为0,底下的buffer已被回收,即使ByteBuf对象还在,对它的各种访问操作都会抛出异常。

3.谁来负责Release

在C时代,我们喜欢让malloc和free成对出现,而在Netty里,因为Handler链的存在,ByteBuf经常要传递到下一个Hanlder去而不复还,所以规则变成了谁是最后使用者,谁负责释放。

另外,更要注意的是各种异常情况,ByteBuf没有成功传递到下一个Hanlder,还在自己地界里的话,一定要进行释放。

3.1 InBound Message

在AbstractNioByteChannel.NioByteUnsafe.read() 处,配置好的ByteBufAllocator创建相应ByteBuf并调用 pipeline.fireChannelRead(byteBuf) 送入Handler链。

根据上面的谁最后谁负责原则,每一个Handler对消息可能有三种处理方式

对原消息不做处理,调用 ctx.fireChannelRead(msg)把原消息往下传,那不用做什么释放。

将原消息转化为新的消息并调用 ctx.fireChannelRead(newMsg)往下传,那必须把原消息release掉。

如果已经不再调用ctx.fireChannelRead(msg)传递任何消息,那更要把原消息release掉。

假设每一个Handler都把消息往下传,Handler并也不知道谁是启动Netty时所设定的Handler链的最后一员,所以Netty会在Handler链的最末补一个TailHandler,如果此时消息仍然是ReferenceCounted类型就会被release掉。

不过如果我们的业务Hanlder不再把消息往下传了,这个TailHandler就派不上用场。

3.2 OutBound Message

要发送的消息通常由应用所创建,并调用 ctx.writeAndFlush(msg) 进入Handler链。在每一个Handler中的处理类似InBound Message,最后消息会来到HeadHandler,再经过一轮复杂的调用,在flush完成后终将被release掉。

3.3 异常发生时的释放

多层的异常处理机制,有些异常处理的地方不一定准确知道ByteBuf之前释放了没有,可以在释放前加上引用计数大于0的判断避免异常;

有时候不清楚ByteBuf被引用了多少次,但又必须在此进行彻底的释放,可以循环调用reelase()直到返回true。

注意:调用writeAndFlush方法,会将ByteBuf的refCnt置为0,从而释放

Netty笔记--ByteBuf释放的更多相关文章

  1. 【Netty】Netty之ByteBuf

    一.前言 前面已经学习了Netty中传输部分,现在接着学习Netty中的ByteBuf. 二.ByteBuf 2.1 ByteBuf API 在网络上传输的数据形式为Byte,Java NIO提供了B ...

  2. Netty笔记——技术点汇总

    目录 · Linux网络IO模型 · 文件描述符 · 阻塞IO模型 · 非阻塞IO模型 · IO复用模型 · 信号驱动IO模型 · 异步IO模型 · BIO编程 · 伪异步IO编程 · NIO编程 · ...

  3. java.neo的ByteBuffer与Netty 的ByteBuf

    JDK的ByteBuffer的缺点: 1.final byte[] hb;这是JDKde ByteBuffer对象中用于存储数据的对象声明;可以看到,其字节数组是被声明为final的,也就是长度是固定 ...

  4. Netty中ByteBuf的引用计数线程安全的实现原理

    原文链接 Netty中ByteBuf的引用计数线程安全的实现原理 代码仓库地址 ByteBuf 实现了ReferenceCounted 接口,实现了引用计数接口,该接口的retain(int) 方法为 ...

  5. Netty的ByteBuf

    https://blog.csdn.net/thinking_fioa/article/details/80795673  netty的ByteBuf知识点

  6. netty笔记(一)--Demo

    Netty是一个Java开源框架,用于传输数据.由server和client组成,封装了Java nio,支持TCP, UDP等协议.这里写了一Demo EchoClientHandler.java ...

  7. Netty之ByteBuf

    本文内容主要参考<<Netty In Action>>,偏笔记向. 网络编程中,字节缓冲区是一个比较基本的组件.Java NIO提供了ByteBuffer,但是使用过的都知道B ...

  8. Netty笔记

    1 基本介绍 Bootstrap Netty应用程序通过设置 bootstrap(引导)类开始,该类提供了一个用于应用程序网络层配置的容器.Bootstrap有两种类型,一种是用于客户端的Bootst ...

  9. Netty 笔记

    1.Netty 是一款异步的事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端. 2.早期Java API 使用的阻塞函数 // 创建一个新的ServerSocket, ...

随机推荐

  1. HDU 1203 I NEED A OFFER! 01背包

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1203 解题思路:简单的01背包,用dp[i]表示花费不超过i时的最大可能性 状态转移方程 dp[i]= ...

  2. ubuntu编译openwrt前端web界面

    openwrt是由Cisco放出源代码的开放无线路由平台.由于是基于linux内核,所以可以将很多linux平台下的软件移植到此平台下,然后让无线路由拥有很多意想不到的功能,例如拿来做BT下载器,音乐 ...

  3. [置顶] VC++界面编程之--使用分层窗口实现界面皮肤

    使用分层界面来实现界面皮肤的好处是:可以保证图片边缘处理不失真,且能用于异形窗口上,如一些不规则的窗口,你很难用SetWindowRgn来达到理想效果. 在很多情况下,界面的漂亮与否,取决于PS的制作 ...

  4. artTemplate的使用总结

    原生语法 使用原生语法,需要导入template-native.js文件. 在HTML中定义模板,注意模板的位置,不要放到被渲染区域,防止模板丢失. <script id="main_ ...

  5. linux 搭建vpn (pptp)

    一.VPN服务器环境说明 操作系统:CentOS release 6.4 (Final) 本地网卡: 复制代码 代码如下: # ifconfig em1 Link encap:Ethernet HWa ...

  6. Struts2学习笔记之s:select标签

    貌似Struts2 标签都快忘光了  今天先来一发struts2的select标签: 首先从简到难,静态赋值: 1 <s:select name="user.sex" lis ...

  7. oracle存储过程含参数的插入数据

    create or replace procedure proczipcodebyzipinsert(   i_zipcode  in  zipcode.zip%type,   i_city in z ...

  8. Appium测试时如何关联到Genymotion模拟器

    一.在Appium里点击左上角的Android Settings里填写模拟器的devicesName,并记得勾选和配置Application Path. (可以通过adb devices命令查询出当前 ...

  9. Swift-Dictionary

    1.字典写法 Dictionary<KeyType,ValueType>,KeyType是你想要储存的键,ValueType是你想要储存的值. 唯一的限制就是KeyType必须是可哈希的, ...

  10. [转] 【开源访谈】Muduo 作者陈硕访谈实录

    关于开源访谈 开源访谈是开源中国推出的一系列针对国内优秀开源软件作者的访谈,以文字的方式记录并传播.我们希望开源访谈能全面的展现国内开源软件.开源软件作者的现状,着实推动国内开源软件的应用与发展. [ ...