DynamicCompositeByteBuf { public ByteBuf retainedSlice(int length) { if (length > readableBytes) { throw new IndexOutOfBoundsException("length > readableBytes"); } if (length <= 0) { return Unpooled.buffer(0); } ByteBuf first = buffers.peek(); int firstLen = first.readableBytes(); if (length <= firstLen) { ByteBuf newBuf = first.retainedSlice(first.readerIndex(), length); return newBuf; } else { int capacity = 2; ByteBuf[] byteBufs = new ByteBuf[capacity]; int i = 0; int offset = 0; ByteBuf newBuf; Iterator<ByteBuf> iterator = buffers.iterator(); while (offset < length && iterator.hasNext()) { ByteBuf next = iterator.next(); int nextLen = next.readableBytes(); if (nextLen <= length - offset) { newBuf = next.retainedSlice(); offset += nextLen; } else { newBuf = next.retainedSlice(next.readerIndex(), length - offset); offset = length; } if (i == capacity) { int newCapacity = capacity * 2; ByteBuf[] newByteBufs = new ByteBuf[newCapacity]; System.arraycopy(byteBufs, 0, newByteBufs, 0, i); byteBufs = newByteBufs; capacity = newCapacity; } byteBufs[i++] = newBuf; } if (i == capacity) { int maxComponentNum = (i > 2) ? i : 2; return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, true, maxComponentNum, byteBufs); } else { ByteBuf[] outBufs = new ByteBuf[i]; System.arraycopy(byteBufs, 0, outBufs, 0, i); int maxComponentNum = (i > 2) ? i : 2; return new CompositeByteBuf(UnpooledByteBufAllocator.DEFAULT, true, maxComponentNum, outBufs); } } } DynamicCompositeByteBuf();  DynamicCompositeByteBuf(int capacity);  DynamicCompositeByteBuf(ByteBuf buf);  DynamicCompositeByteBuf(ByteBuf[] bufs, int offset, int len); int readableBytes(); boolean isEmpty(); boolean hasArray(); byte[] array(); int arrayOffset(); int readerIndex(); boolean isReadable(); ByteBuf nettyByteBuf(); void addBuffer(ByteBuf buffer); ByteBuf readRetainedSlice(int length); ByteBuf retainedSlice(int length); void skipBytes(int length); DynamicCompositeByteBuf readBytes(byte[] dst); DynamicCompositeByteBuf readBytes(byte[] dst, int dstIndex, int length); byte readByte(); short readUnsignedByte(); short readShort(); short readShortLE(); int readUnsignedShort(); int readUnsignedShortLE(); int readInt(); int readIntLE(); long readLong(); long readLongLE(); char readChar(); float readFloat(); float readFloatLE(); double readDouble(); double readDoubleLE(); ByteOrder order(); void release(); @Override String toString();  }
@Test public void testRetainedSlice() { ByteBuf buf1 = Unpooled.buffer(8); buf1.writeInt(1); buf1.writeInt(2); ByteBuf buf2 = Unpooled.buffer(16); buf2.writeLong(10); buf2.writeLong(20); ByteBuf[] bufs = new ByteBuf[2]; bufs[0] = buf1; bufs[1] = buf2; DynamicCompositeByteBuf compositeByteBuf = new DynamicCompositeByteBuf(bufs, 0, 2); Assert.assertTrue(compositeByteBuf.readableBytes() == 24); ByteBuf compositeByteBuf2 = compositeByteBuf.retainedSlice(12); Assert.assertTrue(compositeByteBuf.readableBytes() == 24); Assert.assertTrue(compositeByteBuf2.readInt() == 1); Assert.assertTrue(buf1.refCnt() == 2); Assert.assertTrue(buf2.refCnt() == 2); compositeByteBuf2.release(); Assert.assertTrue(buf1.refCnt() == 1); Assert.assertTrue(buf2.refCnt() == 1); }