使用 Netty 4,当在处理程序中抛出异常时如何处理引用计数对象?

With Netty 4, how do I handle reference counted objects when an exception is thrown inside a handler?

假设我有一个这样的入站通道处理程序:

public class Handler extends ChannelInboundHandlerAdapter {                                                                                                                                                                                                                 

    @Override                                                                                                                                                                                                                                                               
    protected void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {                                                                                                                                                                                    
        // msg is actually a reference counted object                                                                                                                                                                                                                       
    }                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                                                                                                               
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {                                                                                                                                                                              
        // Handle exception here, can't release msg since it's not passed.                                                                                                                                                                                                  
    }                                                                                                                                                                                                                                                                       
}

由于exceptionCaught在其签名中没有收到入站消息,似乎无法确保引用计数对象被释放。看来我被迫将 channelRead 的全部内容包装在 try/catch 块中,以确保我可以在不终止整个过程的情况下正确恢复任何异常。这是真的吗?

您应该在 try-finally 中释放引用计数的对象,如 Netty quick start tutorial 所示。

这可以按如下方式完成:

public class Handler extends ChannelInboundHandlerAdapter {                                                                                                                                                                                                                 

    @Override                                                                                                                                                                                                                                                               
    protected void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {                                                                                                                                                                                    
        try {
            // msg is actually a reference counted object 
        } finally {
            ReferenceCountUtil.release(msg);
        }                                                                                                                                                                                                     
    }                                                                                                                                                                                                                                                                       

    @Override                                                                                                                                                                                                                                                               
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {                                                                                                                                                                              
        // Handle exception here, can't release msg since it's not passed.                                                                                                                                                                                                  
    }                                                                                                                                                                                                                                                                       
}

请注意我调用了 ReferenceCountUtil.release(msg); 而不是 msg.release(),这是因为调用第一个会自动检查是否可以释放有问题的对象,而对于后者你需要将对象转换为不同的类型,然后才能调用释放方法。