Netty ByteBuf释放时机
2021-03-19 01:26
标签:end random uid ESS oid cte ext dir netty ByteBuf释放不当容易造成内存泄漏。 一般情况下,业务handler中使用到的ByteBuf可以分为两类,请求ByteBuf和响应ByteBuf。如下: msg即为请求ByteBuf,而responseByteBuf即为响应ByteBuf。 响应ByteBuf(如writeAndFlush(buf))由netty释放,例如在将HeapBuf转换为DirectBuf的时候释放。 请求ByteBuf,Handler继承SimpleChannelInboundHandler可释放; 请求ByteBuf,fireChannelRead(),由TailContext释放。 对于请求ByteBuf,当业务handler没有继承SimpleChannelInboundHandler,没有fireChannelRead,也没有ReferenceCountUtil.release的话,这时就要考虑内存溢出的情况了。 所以应该时刻记着由最后一个使用的人释放(ReferenceCountUtil.release(byteBuf))。 Netty ByteBuf释放时机 标签:end random uid ESS oid cte ext dir netty 原文地址:https://www.cnblogs.com/AllenDuke/p/12762513.htmlpublic class MyServerHandler extends SimpleChannelInboundHandler
protected final ByteBuf newDirectBuffer(ByteBuf buf) {
final int readableBytes = buf.readableBytes();
if (readableBytes == 0) {
ReferenceCountUtil.safeRelease(buf);
return Unpooled.EMPTY_BUFFER;
}
final ByteBufAllocator alloc = alloc();
if (alloc.isDirectBufferPooled()) {
ByteBuf directBuf = alloc.directBuffer(readableBytes);
directBuf.writeBytes(buf, buf.readerIndex(), readableBytes);
ReferenceCountUtil.safeRelease(buf);//将作为HeapByteBuf的buf引用计数-1,更新状态
return directBuf;
}
final ByteBuf directBuf = ByteBufUtil.threadLocalDirectBuffer();
if (directBuf != null) {
directBuf.writeBytes(buf, buf.readerIndex(), readableBytes);
ReferenceCountUtil.safeRelease(buf);
return directBuf;
}
// Allocating and deallocating an unpooled direct buffer is very expensive; give up.
return buf;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
boolean release = true;
try {
if (acceptInboundMessage(msg)) {
@SuppressWarnings("unchecked")
I imsg = (I) msg;
channelRead0(ctx, imsg);//业务handler只需重写channelRead0
} else {
release = false;
ctx.fireChannelRead(msg);
}
} finally {
if (autoRelease && release) {
ReferenceCountUtil.release(msg);//引用计数-1
}
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {onUnhandledInboundMessage(ctx, msg);}
protected void onUnhandledInboundMessage(ChannelHandlerContext ctx, Object msg) {
onUnhandledInboundMessage(msg);
if (logger.isDebugEnabled()) {
logger.debug("Discarded message pipeline : {}. Channel : {}.",
ctx.pipeline().names(), ctx.channel());
}
}
protected void onUnhandledInboundMessage(Object msg) {
try {
logger.debug(
"Discarded inbound message {} that reached at the tail of the pipeline. " +
"Please check your pipeline configuration.", msg);
} finally {
ReferenceCountUtil.release(msg);//引用计数-1
}
}
上一篇:B/S架构与C/S架构的比较
下一篇:laravel上传图片