范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

netty系列之JVM中的Referencecount原来netty中也有

  简介
  为什么世界上有这么多JAVA的程序员呢?其中一个很重要的原因就是JAVA相对于C++而言,不需要考虑对象的释放,一切都是由垃圾回收器来完成的。在崇尚简单的现代编程世界中,会C++的高手越来越少,会JAVA的程序员越来越多。
  JVM的垃圾回收器中一个很重要的概念就是Reference count,也就是对象的引用计数,用来控制对象是否还被引用,是否可以被垃圾回收。
  netty也是运行在JVM中的,所以JVM中的对象引用计数也适用于netty中的对象。这里我们说的对象引用指的是netty中特定的某些对象,通过对象的引用计数来判断这些对象是否还被使用,如果不再被使用的话就可以把它们(或它们的共享资源)返回到对象池(或对象分配器)。
  这就叫做netty的对象引用计数技术,其中一个最关键的对象就是ByteBuf。 ByteBuf和ReferenceCounted
  netty中的对象引用计数是从4.X版本开始的,ByteBuf是其中最终要的一个应用,它利用引用计数来提高分配和释放性能.
  先来看一下ByteBuf的定义: public abstract class ByteBuf implements ReferenceCounted, Comparable
  可以看到ByteBuf是一个抽象类,它实现了ReferenceCounted的接口。
  ReferenceCounted就是netty中对象引用的基础,它定义了下面几个非常重要的方法,如下所示: int refCnt();  ReferenceCounted retain();  ReferenceCounted retain(int increment);  boolean release();  boolean release(int decrement);
  其中refCnt返回的是当前引用个数,retain用来增加引用,而release用来释放引用。 ByteBuf的基本使用
  刚分配情况下ByteBuf的引用个数是1: ByteBuf buf = ctx.alloc().directBuffer(); assert buf.refCnt() == 1;
  当调用他的release方法之后,refCnt就变成了0: boolean destroyed = buf.release(); assert destroyed; assert buf.refCnt() == 0;
  当调用它的retain方法,refCnt就会加一: ByteBuf buf = ctx.alloc().directBuffer(); assert buf.refCnt() == 1; buf.retain(); assert buf.refCnt() == 2;
  要注意的是,如果ByteBuf的refCnt已经是0了,就表示这个ByteBuf准备被回收了,如果再调用其retain方法,则会抛出IllegalReferenceCountException:refCnt: 0, increment: 1
  所以我们必须在ByteBuf还未被回收之前调用retain方法。
  既然refCnt=0的情况下,不能调用retain()方法,那么其他的方法能够调用吗?
  我们来尝试调用一下writeByte方法:         try {             buf.writeByte(10);         } catch (IllegalReferenceCountException e) {             log.error(e.getMessage(),e);         }
  可以看到,如果refCnt=0的时候,调用它的writeByte方法会抛出IllegalReferenceCountException异常。
  这样看来,只要refCnt=0,说明这个对象已经被回收了,不能够再使用了。 ByteBuf的回收
  既然ByteBuf中保存的有refCnt,那么谁来负责ByteBuf的回收呢?
  netty的原则是谁消费ByteBuf,谁就负责ByteBuf的回收工作。
  在实际的工作中,ByteBuf会在channel中进行传输,根据谁消费谁负责销毁的原则,接收ByteBuf的一方,如果消费了ByteBuf,则需要将其回收。
  这里的回收指的是调用ByteBuf的release()方法。  ByteBuf的衍生方法
  ByteBuf可以从一个parent buff中衍生出很多子buff。这些子buff并没有自己的reference count,它们的引用计数是和parent buff共享的,这些提供衍生buff的方法有:ByteBuf.duplicate(), ByteBuf.slice() 和 ByteBuf.order(ByteOrder)。 buf = directBuffer();         ByteBuf derived = buf.duplicate();         assert buf.refCnt() == 1;         assert derived.refCnt() == 1;
  因为衍生的byteBuf和parent buff共享引用计数,所以如果要将衍生的byteBuf传给其他的流程进行处理的话,需要调用retain()方法: ByteBuf parent = ctx.alloc().directBuffer(512); parent.writeBytes(...);  try {     while (parent.isReadable(16)) {         ByteBuf derived = parent.readSlice(16);         derived.retain();         process(derived);     } } finally {     parent.release(); } ...  public void process(ByteBuf buf) {     ...     buf.release(); }  ChannelHandler中的引用计数
  netty根据是读消息还是写消息,可以分为InboundChannelHandler和OutboundChannelHandler,分别用来读消息和写消息。
  根据谁消费,谁释放的原则,对Inbound消息来说,读取完毕之后,需要调用ByteBuf的release方法: public void channelRead(ChannelHandlerContext ctx, Object msg) {     ByteBuf buf = (ByteBuf) msg;     try {         ...     } finally {         buf.release();     } }
  但是如果你只是将byteBuf重发到channel中供其他的步骤进行处理,则不需要release: public void channelRead(ChannelHandlerContext ctx, Object msg) {     ByteBuf buf = (ByteBuf) msg;     ...     ctx.fireChannelRead(buf); }
  同样的在Outbound中,如果只是简单的重发,则不需要release: public void write(ChannelHandlerContext ctx, Object message, ChannelPromise promise) {     System.err.println("Writing: " + message);     ctx.write(message, promise); }
  如果是处理了消息,则需要release: public void write(ChannelHandlerContext ctx, Object message, ChannelPromise promise) {     if (message instanceof HttpContent) {         // Transform HttpContent to ByteBuf.         HttpContent content = (HttpContent) message;         try {             ByteBuf transformed = ctx.alloc().buffer();             ....             ctx.write(transformed, promise);         } finally {             content.release();         }     } else {         // Pass non-HttpContent through.         ctx.write(message, promise);     } }  内存泄露
  因为reference count是netty自身来进行维护的,需要在程序中手动进行release,这样会带来一个问题就是内存泄露。因为所有的reference都是由程序自己来控制的,而不是由JVM来控制,所以可能因为程序员个人的原因导致某些对象reference count无法清零。
  为了解决这个问题,默认情况下,netty会选择1%的buffer allocations样本来检测他们是否存在内存泄露的情况.
  如果发生泄露,则会得到下面的日志: LEAK: ByteBuf.release() was not called before it"s garbage-collected. Enable advanced leak reporting to find out where the leak occurred. To enable advanced leak reporting, specify the JVM option "-Dio.netty.leakDetectionLevel=advanced" or call ResourceLeakDetector.setLevel()
  上面提到了一个检测内存泄露的level,netty提供了4种level,分别是: DISABLED—禁用泄露检测 SIMPLE –默认的检测方式,占用1% 的buff。 ADVANCED – 也是1%的buff进行检测,不过这个选项会展示更多的泄露信息。 PARANOID – 检测所有的buff。
  具体的检测选项如下: java -Dio.netty.leakDetection.level=advanced ... 总结
  掌握了netty中的引用计数,就掌握了netty的财富密码!
  本文的例子可以参考:learn-netty4 本文已收录于 http://www.flydean.com/43-netty-reference-cound/
  最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
  欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

万元全能大杀器,微星GP75游戏本上手试玩前言每一个ITX玩家其实心里都有一个游戏本的梦想,不管是外星人还是败家国度,既轻巧便捷,又性能强大,典型扮猪吃老虎。但是游戏本不可避免的又存在散热和个性化上面的不足,让我们最终投向活用你的音响系统一起来认识ARC与eARC阜新声艺视听所谓ARC是指音频回传信道(AudioReturnChannel),是2009年HDMI论坛提出HDMI1。4版时所增加的附加功能。如果电视与环绕放大机两方均搭载HDMI1。4端子城市发展差异感觉越来越大了今天从深圳到南京,路上跟一个东北的老乡聊了聊,他疫情前在上海做程序员,疫情期间公司倒闭,顺便就回东北老家了。他觉得东北这几年开始走下坡路,机会少,工资又低,连他们这个知名的软件外包张艺谋陈建斌周迅都来了,4月的电影院终于要爆3月的电影院,实在是太过冷清。票房粗报25亿元,排七年内全国电影票房倒数。春节档余热未散,李焕英冲破50亿大关,拿下中国影史第二好莱坞大片方面,仅有阿凡达重映以及月底的哥斯拉大战金确保大型户外演出灯光控制系统安全的三要素阜新声艺视听在大型户外文艺演出活动中,灯光控制系统是现场灯光的中枢,其性能直接关系到整场演出的效果。灯光控制系统主要包括灯光控制台调光柜或调光硅箱换色器功率放大器等设备。在控制系统指令下,灯具我的音响器材听起来很吵耳,怎么办?阜新声艺视听答案很简单到市场捡一些盛载鸡蛋的纸盘便可以帮到你。在一个有限的空间内,声音传播是一件极复杂的事情。声音觉得吵耳,是因为一些不必要的声音存在着,包括背景噪音器材失真等,而最令人头痛的调音实践中的一些技巧阜新声艺视听人耳对音色的感觉比较灵敏,可以直接判断声音是否逼真。音色在调音方面不可不谓之重要,稍对音色处理不好,就会造成声音单调,枯燥乏味,更有甚者,造成乐器或者演唱产生严重的失真。今天就来分用音响欣赏音乐的时候,喇叭的摆放重要吗?阜新声艺视听我们听音乐时所感知的定位感是怎么来的?这是跟声学理论中的领先效应(PrecedenceEffect)有关。有关这样的研究,最早在1948年有LotharCremer发表的相关论文L华为前自动驾驶部长苏箐被调离据互联网消息,之前在2021世界人工智能大会上锐评特斯拉高事故率就是在杀人!的华为前自动驾驶部长苏箐,已经调离自动驾驶部门,目前进入战略预备队接受训战。据悉,此次人事调动由任正非亲骁龙865!高通推出骁龙870芯片,摩托罗拉新机全球首发昨天晚间,高通正式官宣了传闻已久的骁龙865加了又加版本骁龙870SoC。这颗芯片相比骁龙865的最主要升级是大核主频提高到了3。2GHz,相比骁龙865提高了100MHz,比骁龙QQ远程协助升级版?绿厂屏幕共享功能轻松解决老人用机难题有了手机微信之后,就很久没打开过QQ了。以前除了用QQ聊天之外,还经常会用它的远程协助功能。毕竟用它来控制家里的电脑或者帮亲朋好友远程解决问题还是非常方便的。这样的功能固然好用,除