Netty SslHandler 抛出 IllegalReferenceCountException
Netty SslHandler throws IllegalReferenceCountException
我正在使用 netty 4.0 编写客户端-服务器应用程序。36.Final
一位测试工程师在客户端遇到了这个问题:
io.netty.handler.codec.DecoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:418)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:112)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1072)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:904)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
... 15 common frames omitted
渠道管道:
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(sslContext.newHandler(ch.alloc()));
pipeline.addLast(new AsnMessageDecoder());
pipeline.addLast(new AsnMessageEncoder());
pipeline.addLast(dataChannelHandler);
}
有时我向管道添加了另一个处理程序:
channel.pipeline().addFirst("idleStateHandler", new IdleStateHandler(180, 0, 0));
有两个ChannelInboundHandler
的
public class AsnMessageDecoder extends ReplayingDecoder {
private static final Logger log = LoggerFactory.getLogger(AsnMessageDecoder.class);
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
DERCoder coder = Asn.getDERCoder();
coder.disableEncoderDebugging();
coder.disableDecoderDebugging();
coder.enableEncoderConstraints();
coder.enableDecoderConstraints();
coder.enableAutomaticEncoding();
coder.enableAutomaticDecoding();
coder.enableContainedValueEncoding();
coder.enableContainedValueDecoding();
try (ByteBufInputStream is = new ByteBufInputStream(in)) {
out.add(coder.decode(is, new Message()));
} catch (Exception e) {
log.error("Failed to decode message", e);
}
}
还有一个:
abstract class BaseChannelHandler<T extends ChannelContext> extends SimpleChannelInboundHandler<Message> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final T channelContext;
private final ClientConfiguration clientConfiguration;
private final Writer writer;
private final ClientService service;
BaseChannelHandler(T channelContext,
ClientConfiguration clientConfiguration,
Writer writer,
ClientService service) {
this.channelContext = channelContext;
this.clientConfiguration = clientConfiguration;
this.writer = writer;
this.service = service;
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelRegistered", getClass().getSimpleName());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelActive", getClass().getSimpleName());
channelContext.connectState();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
log.debug("{} channelRead0 msg = {}", getClass().getSimpleName(), msg);
channelContext.handleMessage(msg);
if (clientConfiguration.isWritingOutputEnabled()) {
writer.writeXml(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error(getClass().getSimpleName() + " exceptionCaught", cause);
ctx.close();
service.stop();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelInactive", getClass().getSimpleName());
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelUnregistered", getClass().getSimpleName());
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
ctx.disconnect();
}
}
我无法重现问题。在我的本地机器上它工作正常。查看 wirweshark 没有给我任何提示。看起来像正常断开连接。
我不太确定下一步该怎么做才能定位这个问题。你能给我一些解决这个问题的下一步建议吗?
所以这似乎是 netty 版本(很旧)中的一个错误。升级到 4.1。24.Final 修复了它。
我正在使用 netty 4.0 编写客户端-服务器应用程序。36.Final
一位测试工程师在客户端遇到了这个问题:
io.netty.handler.codec.DecoderException: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:418)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:245)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:266)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:292)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:278)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:962)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:528)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:485)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:399)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:371)
at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:112)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1
at io.netty.buffer.AbstractReferenceCountedByteBuf.release(AbstractReferenceCountedByteBuf.java:101)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1072)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:904)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:387)
... 15 common frames omitted
渠道管道:
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(sslContext.newHandler(ch.alloc()));
pipeline.addLast(new AsnMessageDecoder());
pipeline.addLast(new AsnMessageEncoder());
pipeline.addLast(dataChannelHandler);
}
有时我向管道添加了另一个处理程序:
channel.pipeline().addFirst("idleStateHandler", new IdleStateHandler(180, 0, 0));
有两个ChannelInboundHandler
的
public class AsnMessageDecoder extends ReplayingDecoder {
private static final Logger log = LoggerFactory.getLogger(AsnMessageDecoder.class);
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
DERCoder coder = Asn.getDERCoder();
coder.disableEncoderDebugging();
coder.disableDecoderDebugging();
coder.enableEncoderConstraints();
coder.enableDecoderConstraints();
coder.enableAutomaticEncoding();
coder.enableAutomaticDecoding();
coder.enableContainedValueEncoding();
coder.enableContainedValueDecoding();
try (ByteBufInputStream is = new ByteBufInputStream(in)) {
out.add(coder.decode(is, new Message()));
} catch (Exception e) {
log.error("Failed to decode message", e);
}
}
还有一个:
abstract class BaseChannelHandler<T extends ChannelContext> extends SimpleChannelInboundHandler<Message> {
private final Logger log = LoggerFactory.getLogger(getClass());
private final T channelContext;
private final ClientConfiguration clientConfiguration;
private final Writer writer;
private final ClientService service;
BaseChannelHandler(T channelContext,
ClientConfiguration clientConfiguration,
Writer writer,
ClientService service) {
this.channelContext = channelContext;
this.clientConfiguration = clientConfiguration;
this.writer = writer;
this.service = service;
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelRegistered", getClass().getSimpleName());
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelActive", getClass().getSimpleName());
channelContext.connectState();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Message msg) throws Exception {
log.debug("{} channelRead0 msg = {}", getClass().getSimpleName(), msg);
channelContext.handleMessage(msg);
if (clientConfiguration.isWritingOutputEnabled()) {
writer.writeXml(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error(getClass().getSimpleName() + " exceptionCaught", cause);
ctx.close();
service.stop();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelInactive", getClass().getSimpleName());
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
log.debug("{} channelUnregistered", getClass().getSimpleName());
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
ctx.disconnect();
}
}
我无法重现问题。在我的本地机器上它工作正常。查看 wirweshark 没有给我任何提示。看起来像正常断开连接。 我不太确定下一步该怎么做才能定位这个问题。你能给我一些解决这个问题的下一步建议吗?
所以这似乎是 netty 版本(很旧)中的一个错误。升级到 4.1。24.Final 修复了它。