根据这本书Netty in Action v10, reference counting是用来处理汇集的ByteBuf.但是JVM并不知道netty引用计数,所以JVM仍然可以GC ByteBuf.如果是这样,为什么我们仍然需要关心引用计数和手动调用release()方法?
我引用了<Netty in Action v10>中的一些来添加一些上下文.
引用计数的权衡之一是用户在使用消息时必须小心.虽然JVM仍然能够GC这样的消息(因为它不知道引用计数),但是这个消息不会被放回到之前可能获得它的池中.因此,如果您不仔细发布这些消息,那么在某一点上您将耗尽资源的可能性很大.
还有一些相关的线程: Netty 4中的缓冲区所有权:缓冲区生命周期是如何管理的?
https://blog.twitter.com/2013/netty-4-at-twitter-reduced-gc-overhead
(以下是我的理解.)
A ByteBuf可以从2个角度分类:
1. Pooled or Unpooled
2. Heap-based or Direct
Run Code Online (Sandbox Code Playgroud)
所以可以有4种组合:
(a) Pooled Heap-based
(b) Pooled Direct
(c) Unpooled Heap-based
(d) Unpooled Direct
Run Code Online (Sandbox Code Playgroud)
只有(a)和(c)受JVM GC机制的影响,因为它们是基于堆的.
在<Netty in Action v10>的上述引文中,我认为该消息意味着一个Java对象,它位于(a)类别中.
一个最终的规则是,如果一个Java对象是GCed,它就完全消失了.以下是我认为Netty的作用:
对于(a),Netty分配器必须诱使JVM GC相信该对象永远不应该被GC.然后使用ref count将对象移出/移回池中.这是生命周期的另一种形式.
对于(b),不涉及JVM GC,因为它不是基于JVM堆的.并且Netty分配器需要使用ref计数来将对象移出/返回池中.
对于(c),JVM GC负责控制对象的生命.Netty allocator只提供分配对象的API.
对于(d),不涉及JVM GC.并且不需要汇集.所以Netty allocator只需要提供API来分配/释放对象.
我一直在尝试编写一个HTTP客户端来同时获取多个提要(最多1k),这也是学习Netty 4的练习.
我的问题是,如果有一个很好的解释,新的ByteBuf基础设施如何工作?谁"拥有"他们,他们是如何分享的(是吗?)?ChannelPipeline中的每个ChannelHandler都有它自己的ByteBuf吗?
这是一个令我困惑的例子:
我将以下类的实例添加到HTTP客户端管道:
public class MyFilter extends MessageToMessageDecoder<HttpObject> {
@Override
protected Object decode(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
// do some work, but leave msg unchanged
BufUtil.retain(msg); // Why do I need to call BufUtil.retain(msg) ???
return msg;
}
Run Code Online (Sandbox Code Playgroud)
如果我没有在msg上调用BufUtil.retain,它似乎得到了GCd,我得到了各种各样的虚假错误.
netty ×2