From bbe880f5ea05b6a8769e77c2df801107a1343502 Mon Sep 17 00:00:00 2001 From: Ronald Chen Date: Fri, 28 Nov 2014 11:39:15 -0800 Subject: [PATCH] Rocumented decoder pitfalls to avoid mistakes found in [#3184] --- .../handler/codec/ByteToMessageDecoder.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java index 35dcc00668..e7c8bc5149 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -41,8 +41,29 @@ import java.util.List; * } * * + *

Frame detection

+ *

+ * Generally frame detection should be handled earlier in the pipeline by adding a + * {@link DelimiterBasedFrameDecoder}, {@link FixedLengthFrameDecoder}, {@link LengthFieldBasedFrameDecoder}, + * or {@link LineBasedFrameDecoder}. + *

+ * If a custom frame decoder is required, then one needs to be careful when implementing + * one with {@link ByteToMessageDecoder}. Ensure there are enough bytes in the buffer for a + * complete frame by checking {@link ByteBuf#readableBytes()}. If there are not enough bytes + * for a complete frame, return without modify the reader index to allow more bytes to arrive. + *

+ * To check for complete frames without modify the reader index, use methods like {@link ByteBuf#getInt(int)}. + * One MUST use the reader index when using methods like {@link ByteBuf#getInt(int)}. + * For example calling in.getInt(0) is assuming the frame starts at the beginning of the buffer, which + * is not always the case. Use in.getInt(in.readerIndex()) instead. + *

Pitfalls

+ *

* Be aware that sub-classes of {@link ByteToMessageDecoder} MUST NOT * annotated with {@link @Sharable}. + *

+ * Some methods such as {@link ByteBuf.readBytes(int)} will cause a memory leak if the returned buffer + * is not released or added to the out {@link List}. Use derived buffers like {@link ByteBuf.readSlice(int)} + * to avoid leaking memory. */ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter {