From 5c55a59de4a6cd9cb8075848874e1423cfb4474d Mon Sep 17 00:00:00 2001 From: Francesco Nigro Date: Tue, 19 Dec 2023 14:20:22 +0100 Subject: [PATCH] Redo fix scalability issue due to checkcast on context's invoke operations Motivation: ChannelDuplexHandler can implements both ChannelOutboundHandler and ChannelInboundHandler causing a scalability issue due to checkcast due to https://bugs.openjdk.org/browse/JDK-8180450 Not only: there are different classes eg Http2ConnectionHandler, which implement them transitively, by using one of the 2 existing adapters (ChannelInboundAdapter, ChanneOutboundAdapters). The existing change at https://github.com/netty/netty/pull/12806 was fixing only the duplex cases, but others like the above one was still affected. Modifications: Replace the duplex type checks with broader inbound adapter ones, given that duplex is still based on it. Add outbound adapters type checks in addition to duplex ones. Result: More scalable adapters-based channel handler operations. --- .../AbstractChannelHandlerContext.java | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java index 0128e776b071..d3953f47626e 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java @@ -170,8 +170,8 @@ private void invokeChannelRegistered() { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.channelRegistered(this); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).channelRegistered(this); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).channelRegistered(this); } else { ((ChannelInboundHandler) handler).channelRegistered(this); } @@ -213,8 +213,8 @@ private void invokeChannelUnregistered() { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.channelUnregistered(this); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).channelUnregistered(this); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).channelUnregistered(this); } else { ((ChannelInboundHandler) handler).channelUnregistered(this); } @@ -256,8 +256,8 @@ private void invokeChannelActive() { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.channelActive(this); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).channelActive(this); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).channelActive(this); } else { ((ChannelInboundHandler) handler).channelActive(this); } @@ -299,8 +299,8 @@ private void invokeChannelInactive() { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.channelInactive(this); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).channelInactive(this); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).channelInactive(this); } else { ((ChannelInboundHandler) handler).channelInactive(this); } @@ -394,8 +394,8 @@ private void invokeUserEventTriggered(Object event) { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.userEventTriggered(this, event); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).userEventTriggered(this, event); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).userEventTriggered(this, event); } else { ((ChannelInboundHandler) handler).userEventTriggered(this, event); } @@ -522,8 +522,8 @@ private void invokeChannelWritabilityChanged() { final DefaultChannelPipeline.HeadContext headContext = pipeline.head; if (handler == headContext) { headContext.channelWritabilityChanged(this); - } else if (handler instanceof ChannelDuplexHandler) { - ((ChannelDuplexHandler) handler).channelWritabilityChanged(this); + } else if (handler instanceof ChannelInboundHandlerAdapter) { + ((ChannelInboundHandlerAdapter) handler).channelWritabilityChanged(this); } else { ((ChannelInboundHandler) handler).channelWritabilityChanged(this); } @@ -600,6 +600,8 @@ private void invokeBind(SocketAddress localAddress, ChannelPromise promise) { headContext.bind(this, localAddress, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).bind(this, localAddress, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).bind(this, localAddress, promise); } else { ((ChannelOutboundHandler) handler).bind(this, localAddress, promise); } @@ -653,6 +655,8 @@ private void invokeConnect(SocketAddress remoteAddress, SocketAddress localAddre headContext.connect(this, remoteAddress, localAddress, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).connect(this, remoteAddress, localAddress, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).connect(this, remoteAddress, localAddress, promise); } else { ((ChannelOutboundHandler) handler).connect(this, remoteAddress, localAddress, promise); } @@ -703,6 +707,8 @@ private void invokeDisconnect(ChannelPromise promise) { headContext.disconnect(this, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).disconnect(this, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).disconnect(this, promise); } else { ((ChannelOutboundHandler) handler).disconnect(this, promise); } @@ -749,6 +755,8 @@ private void invokeClose(ChannelPromise promise) { headContext.close(this, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).close(this, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).close(this, promise); } else { ((ChannelOutboundHandler) handler).close(this, promise); } @@ -795,6 +803,8 @@ private void invokeDeregister(ChannelPromise promise) { headContext.deregister(this, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).deregister(this, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).deregister(this, promise); } else { ((ChannelOutboundHandler) handler).deregister(this, promise); } @@ -835,6 +845,8 @@ private void invokeRead() { headContext.read(this); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).read(this); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).read(this); } else { ((ChannelOutboundHandler) handler).read(this); } @@ -877,6 +889,8 @@ private void invokeWrite0(Object msg, ChannelPromise promise) { headContext.write(this, msg, promise); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).write(this, msg, promise); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).write(this, msg, promise); } else { ((ChannelOutboundHandler) handler).write(this, msg, promise); } @@ -921,6 +935,8 @@ private void invokeFlush0() { headContext.flush(this); } else if (handler instanceof ChannelDuplexHandler) { ((ChannelDuplexHandler) handler).flush(this); + } else if (handler instanceof ChannelOutboundHandlerAdapter) { + ((ChannelOutboundHandlerAdapter) handler).flush(this); } else { ((ChannelOutboundHandler) handler).flush(this); }