Netty 为什么FullHttpResponse引用计数的行为会因底层ByteBuf实现的不同而有所不同?

Netty 为什么FullHttpResponse引用计数的行为会因底层ByteBuf实现的不同而有所不同?,netty,Netty,我在EmbeddedChannel上遇到漏洞问题,我使用它将原始http响应解析为FullHttpResponse。在分析过程中,我注意到作为“输入”发送到通道中的ByteBuf的引用计数根据其实现的不同而表现不同,这似乎很奇怪 作为参考,以下是我用来解析原始输入的方法: private FullHttpResponse解码httpresponse(ByteBuf responseBuff){ EmbeddedChannel=新的EmbeddedChannel(新的HttpResponsedCo

我在
EmbeddedChannel
上遇到漏洞问题,我使用它将原始http响应解析为
FullHttpResponse
。在分析过程中,我注意到作为“输入”发送到通道中的ByteBuf的引用计数根据其实现的不同而表现不同,这似乎很奇怪

作为参考,以下是我用来解析原始输入的方法:

private FullHttpResponse解码httpresponse(ByteBuf responseBuff){
EmbeddedChannel=新的EmbeddedChannel(新的HttpResponsedCoder(),新的HttpObjectAggregator(9999999));
试一试{
频道写入绑定(responseBuff);
channel.flush();
通道。完成();
返回channel.readInbound();
}最后{
channel.close();
channel.finishAndReleaseAll();
}
}
让我们使用一个简单的
ByteBuf
I从先前转储到文件中的http响应创建并进行一些测试,下面是我的输出(数字是对象的引用计数):

  • [1] :当我们创建
    FullHttpResponse
    时,输入ByteBuf上的refCount将减少1
  • [2] :当解除分配
    FullHttpResponse
    时(refCount达到0),它不会传播到基础CompositeByteBuf
这种行为上的差异令人困惑,并使正确的引用计数变得困难(这是一个简化的示例,在实际应用中,分层缓冲区的纠缠使其更加困难)

有人能解释一下为什么上述行为与
ByteBuf
CompositeByteBuf
有所不同,或者我能做些什么使行为一致且可预测?或者这可能是一个应该解决的bug

>>>---------- Test with ByteBuf ------------<<<
>>> [buf]  : 1
buf.retain()
>>> [buf]  : 2
resp = decodeHttpResponse(cbuf) => io.netty.handler.codec.http.HttpObjectAggregator$AggregatedFullHttpResponse
>>> [buf]  : 2                  // [1]
>>> [resp] : 1                  // 
resp.retain()
>>> [buf]  : 2
>>> [resp] : 2
resp.release()
>>> [buf]  : 2
>>> [resp] : 1
resp.release()                  //
>>> [buf]  : 1                  // [2]
>>> [resp] : 0                  //
>>>---------- Test with CompositeByteBuf ------------<<<
>>> [buf]  : 1
buf.retain()
>>> [buf]  : 2
cbuf = buf.alloc().compositeBuffer()
>>> [buf]  : 2
>>> [cbuf] : 1
cbuf.addComponent(true, buf)
>>> [buf]  : 2
>>> [cbuf] : 1
cbuf.retain()
>>> [buf]  : 2
>>> [cbuf] : 2
resp = decodeHttpResponse(cbuf) => io.netty.handler.codec.http.HttpObjectAggregator$AggregatedFullHttpResponse
>>> [buf]  : 2              //
>>> [cbuf] : 1              // [1]
>>> [resp] : 1              //
resp.retain()
>>> [buf]  : 2
>>> [cbuf] : 1
>>> [resp] : 2
resp.release()
>>> [buf]  : 2
>>> [cbuf] : 1
>>> [resp] : 1
resp.release()
>>> [buf]  : 2              //
>>> [cbuf] : 1              // [2]
>>> [resp] : 0              //