netty4.0 关于buffer

NIO中的buffer很经典,但是也需要小心翼翼。比如,flip如果不用好,就可能出错。
netty中重新封装了buffer,于是ByteBuf出现了。
public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
public ByteBufAllocator alloc();
public byte[] array();
public int arrayOffset();
public int bytesBefore(byte);
public int bytesBefore(ByteBufIndexFinder);
public int bytesBefore(int, byte);
public int bytesBefore(int, ByteBufIndexFinder);
public int bytesBefore(int, int, byte);
public int bytesBefore(int, int, byteBufIndexFinder);
public int capacity();
public ByteBuf capacity(int);
public ByteBuf clear();
public int compareTo(ByteBuf);
public ByteBuf copy();
public ByteBuf copy(int, int);
public ByteBuf discardReadBytes();
public ByteBuf duplicate();
public ByteBuf ensureWritableBytes(int);
public ByteBuf ensureWritableBytes(int, boolean);
public boolean equals(Object);
...
}

实在是太多,不一一罗列。这里注意的是,readerIndex()和writerIndex()说明有两个指针,这样的话,在0和readerIndex()之间的数据就表示已经读过的,调用discardReadBytes()就可以删除这些数据,类似NIO中的compact
这样做的好处是减少不必要的拷贝。指针是个宝。
当然这里的ByteBuf也把ByteBuffer中该有的都不落下。同时看接口,ChannelBuf只是一个方法 type()返回表明是byte还是message数据。comparable大家都很熟悉了。

ByteBuf是个接口,她有两个子接口
CompositeByteBuf 和 UnsafeByteBuf
CompositeByteBuf 就是多个ByteBuf的组合。
UnsafeByteBuf则是增加了一些方法,可以操作NIO。
接下来有 AbstractByteBuf,ReplayingDecoderBuffer和SwappedByteBuf
当然这些都不怎么用,SwappedByteBuf直接把传入的ByteBuf的字节序弄反就是了。
ReplayingDecoderBuffer则是在terminate以后,才返回capacity,这样可以用于在接受数据时,如果数据接收齐全了,就使用terminate()函数。


在AbstractByteBuf的强大实现下,开始有很多的子类了。大家可以看看。
这里要说常用的。例如UnpooledHeapByteBuf和UnpooledDirectByteBuf
这两个类基本上就是ByteBuf的实现类,工具类UnpooledByteBufAllocator正是通过返回他们得到想要的ByteBuf实例。文档上建议我们使用Unpooled工具类来创建这些ByteBuf,例如 directBuffer() 或者 wrappedBuffer(byte[]),wrappedBuffer(ByteBuffer) 等。

UnpooledDirectByteBuf很有意思,请看
private static final Field CLEANER_FIELD;

    static {
        ByteBuffer direct = ByteBuffer.allocateDirect(1);
        Field cleanerField;
        try {
            cleanerField = direct.getClass().getDeclaredField("cleaner");
            cleanerField.setAccessible(true);
            Cleaner cleaner = (Cleaner) cleanerField.get(direct);
            cleaner.clean();
        } catch (Throwable t) {
            cleanerField = null;
        }
        CLEANER_FIELD = cleanerField;
    }


这里正是NIO中一个头疼的问题,就是direct memory的回收。这里给出一个解决办法。通常我们都是使用了System.gc()去建议JVM回收。
下面是使用。
 private static void freeDirect(ByteBuffer buffer) {
        if (CLEANER_FIELD == null) {
            // Doomed to wait for GC.
            return;
        }

        Cleaner cleaner;
        try {
            cleaner = (Cleaner) CLEANER_FIELD.get(buffer);
            cleaner.clean();
        } catch (Throwable t) {
            // Nothing we can do here.
        }
    }



netty4.0 buffer,使用了读写指针直接对byte进行封装。并没有在NIO的buffer上再次封装,对于NIO buffer,则是直接使用byte array包装。

你可能感兴趣的:(buffer)