diff --git a/src/main/java/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.java b/src/main/java/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.java index 65d59b6109..4daaf35dcd 100644 --- a/src/main/java/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/frame/LengthFieldBasedFrameDecoder.java @@ -16,8 +16,10 @@ package org.jboss.netty.handler.codec.frame; import org.jboss.netty.buffer.ChannelBuffer; +import org.jboss.netty.buffer.ChannelBufferFactory; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.handler.codec.serialization.ObjectDecoder; /** * A decoder that splits the received {@link ChannelBuffer}s dynamically by the @@ -364,6 +366,33 @@ public class LengthFieldBasedFrameDecoder extends FrameDecoder { "than initialBytesToStrip: " + initialBytesToStrip); } buffer.skipBytes(initialBytesToStrip); - return buffer.readBytes(frameLengthInt - initialBytesToStrip); + + // extract frame + int readerIndex = buffer.readerIndex(); + int actualFrameLength = frameLengthInt - initialBytesToStrip; + ChannelBuffer frame = extractFrame(buffer, readerIndex, actualFrameLength); + buffer.readerIndex(readerIndex + actualFrameLength); + return frame; + } + + /** + * Extract the sub-region of the specified buffer. This method is called by + * {@link #decode(ChannelHandlerContext, Channel, ChannelBuffer)} for each + * frame. The default implementation returns a copy of the sub-region. + * For example, you could override this method to use an alternative + * {@link ChannelBufferFactory}. + *

+ * If you are sure that the frame and its content are not accessed after + * the current {@link #decode(ChannelHandlerContext, Channel, ChannelBuffer)} + * call returns, you can even avoid memory copy by returning the sliced + * sub-region (i.e. return buffer.slice(index, length)). + * It's often useful when you convert the extracted frame into an object. + * Refer to the source code of {@link ObjectDecoder} to see how this method + * is overridden to avoid memory copy. + */ + protected ChannelBuffer extractFrame(ChannelBuffer buffer, int index, int length) { + ChannelBuffer frame = buffer.factory().getBuffer(length); + frame.writeBytes(buffer, index, length); + return frame; } } diff --git a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java index cc2e167b63..3bf80a82ca 100644 --- a/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java +++ b/src/main/java/org/jboss/netty/handler/codec/serialization/ObjectDecoder.java @@ -94,4 +94,9 @@ public class ObjectDecoder extends LengthFieldBasedFrameDecoder { return new CompactObjectInputStream( new ChannelBufferInputStream(frame), classLoader).readObject(); } + + @Override + protected ChannelBuffer extractFrame(ChannelBuffer buffer, int index, int length) { + return buffer.slice(index, length); + } }