diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java index 43cf0302bc..145d0275bd 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageCodec.java @@ -56,6 +56,10 @@ public abstract class ByteToMessageCodec extends ChannelDuplexHandler outboundMsgMatcher = TypeParameterMatcher.find(this, ByteToMessageCodec.class, "I"); } + protected ByteToMessageCodec(Class outboundMessageType) { + outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType); + } + @Override public void beforeAdd(ChannelHandlerContext ctx) throws Exception { decoder.beforeAdd(ctx); diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java index 376e23db40..9aec6d9823 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToByteEncoder.java @@ -40,6 +40,12 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter; */ public abstract class MessageToByteEncoder extends ChannelOutboundMessageHandlerAdapter { + protected MessageToByteEncoder() { } + + protected MessageToByteEncoder(Class outboundMessageType) { + super(outboundMessageType); + } + @Override public void flush(ChannelHandlerContext ctx, I msg) throws Exception { try { diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java index 0cc61a8de3..fb4b586405 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageCodec.java @@ -90,6 +90,12 @@ public abstract class MessageToMessageCodec outboundMsgMatcher = TypeParameterMatcher.find(this, MessageToMessageCodec.class, "OUTBOUND_IN"); } + protected MessageToMessageCodec( + Class inboundMessageType, Class outboundMessageType) { + inboundMsgMatcher = TypeParameterMatcher.get(inboundMessageType); + outboundMsgMatcher = TypeParameterMatcher.get(outboundMessageType); + } + @Override @SuppressWarnings("unchecked") public MessageBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageDecoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageDecoder.java index a9b7311a84..0c52e0002e 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageDecoder.java @@ -44,6 +44,12 @@ import io.netty.channel.ChannelInboundMessageHandlerAdapter; */ public abstract class MessageToMessageDecoder extends ChannelInboundMessageHandlerAdapter { + protected MessageToMessageDecoder() { } + + protected MessageToMessageDecoder(Class inboundMessageType) { + super(inboundMessageType); + } + @Override public final void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception { ctx.nextInboundMessageBuffer().unfoldAndAdd(decode(ctx, msg)); diff --git a/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java b/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java index 3263b8fc0d..dfe07e7739 100644 --- a/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java +++ b/codec/src/main/java/io/netty/handler/codec/MessageToMessageEncoder.java @@ -42,6 +42,12 @@ import io.netty.channel.ChannelOutboundMessageHandlerAdapter; */ public abstract class MessageToMessageEncoder extends ChannelOutboundMessageHandlerAdapter { + protected MessageToMessageEncoder() { } + + protected MessageToMessageEncoder(Class outboundMessageType) { + super(outboundMessageType); + } + @Override public final void flush(ChannelHandlerContext ctx, I msg) throws Exception { try { diff --git a/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java b/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java index 0c71ad7647..ab9a676b45 100644 --- a/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java +++ b/common/src/main/java/io/netty/util/internal/TypeParameterMatcher.java @@ -30,7 +30,45 @@ public abstract class TypeParameterMatcher { private static final TypeParameterMatcher NOOP = new NoOpTypeParameterMatcher(); private static final Object TEST_OBJECT = new Object(); - private static final ThreadLocal, Map>> typeMap = + private static final ThreadLocal, TypeParameterMatcher>> getCache = + new ThreadLocal, TypeParameterMatcher>>() { + @Override + protected Map, TypeParameterMatcher> initialValue() { + return new IdentityHashMap, TypeParameterMatcher>(); + } + }; + + public static TypeParameterMatcher get(final Class parameterType) { + final Map, TypeParameterMatcher> getCache = TypeParameterMatcher.getCache.get(); + + TypeParameterMatcher matcher = getCache.get(parameterType); + if (matcher == null) { + if (parameterType == Object.class) { + matcher = NOOP; + } else if (PlatformDependent.hasJavassist()) { + try { + matcher = JavassistTypeParameterMatcherGenerator.generate(parameterType); + matcher.match(TEST_OBJECT); + } catch (IllegalAccessError e) { + // Happens if parameterType is not public. + matcher = null; + } catch (Exception e) { + // Will not usually happen, but just in case. + matcher = null; + } + } + + if (matcher == null) { + matcher = new ReflectiveMatcher(parameterType); + } + + getCache.put(parameterType, matcher); + } + + return matcher; + } + + private static final ThreadLocal, Map>> findCache = new ThreadLocal, Map>>() { @Override protected Map, Map> initialValue() { @@ -41,37 +79,18 @@ public abstract class TypeParameterMatcher { public static TypeParameterMatcher find( final Object object, final Class parameterizedSuperclass, final String typeParamName) { - final Map, Map> typeMap = TypeParameterMatcher.typeMap.get(); + final Map, Map> findCache = TypeParameterMatcher.findCache.get(); final Class thisClass = object.getClass(); - Map map = typeMap.get(thisClass); + Map map = findCache.get(thisClass); if (map == null) { map = new HashMap(); - typeMap.put(thisClass, map); + findCache.put(thisClass, map); } TypeParameterMatcher matcher = map.get(typeParamName); if (matcher == null) { - Class messageType = find0(object, parameterizedSuperclass, typeParamName); - if (messageType == Object.class) { - matcher = NOOP; - } else if (PlatformDependent.hasJavassist()) { - try { - matcher = JavassistTypeParameterMatcherGenerator.generate(messageType); - matcher.match(TEST_OBJECT); - } catch (IllegalAccessError e) { - // Happens if messageType is not public. - matcher = null; - } catch (Exception e) { - // Will not usually happen, but just in case. - matcher = null; - } - } - - if (matcher == null) { - matcher = new ReflectiveMatcher(messageType); - } - + matcher = get(find0(object, parameterizedSuperclass, typeParamName)); map.put(typeParamName, matcher); } diff --git a/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java b/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java index f601fb31d3..f8149e7624 100644 --- a/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java +++ b/transport/src/main/java/io/netty/channel/ChannelInboundMessageHandlerAdapter.java @@ -63,6 +63,10 @@ public abstract class ChannelInboundMessageHandlerAdapter msgMatcher = TypeParameterMatcher.find(this, ChannelInboundMessageHandlerAdapter.class, "I"); } + protected ChannelInboundMessageHandlerAdapter(Class inboundMessageType) { + msgMatcher = TypeParameterMatcher.get(inboundMessageType); + } + @Override public MessageBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception { return Unpooled.messageBuffer(); diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java b/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java index 5bdd85243e..e913134d17 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundMessageHandlerAdapter.java @@ -47,6 +47,10 @@ public abstract class ChannelOutboundMessageHandlerAdapter msgMatcher = TypeParameterMatcher.find(this, ChannelOutboundMessageHandlerAdapter.class, "I"); } + protected ChannelOutboundMessageHandlerAdapter(Class outboundMessageType) { + msgMatcher = TypeParameterMatcher.get(outboundMessageType); + } + protected final boolean isCloseOnFailedFlush() { return closeOnFailedFlush; }