1. 程式人生 > >Netty整理(三)

Netty整理(三)

Netty整理(二)

ByteBuf:是資料容器(位元組容器)

        JDK ByteBuffer
            共用讀寫索引,每次讀寫操作都需要Flip()
            擴容麻煩,而且擴容後容易造成浪費 關於ByteBuffer的使用方法可以參考序列化和反序列化的三種方法 ,裡面有Netty 3的ChannelBuffer,因為現在Netty 3用的比較少,當作參考就好。

        Netty ByteBuf
            讀寫使用不同的索引,所以操作便捷
            自動擴容,使用便捷

我們現在來看一下ByteBuf的原始碼。

public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf>

我們可以看到ByteBuf是一個抽象類,它裡面幾乎大部分都是抽象方法。

繼承ByteBuf的是一個AbstractByteBuf的抽象類,而讀寫索引的屬性就在該類中。

public abstract class AbstractByteBuf extends ByteBuf
int readerIndex;  //讀索引
int writerIndex;  //寫索引
private int markedReaderIndex;  //標記當前讀索引的位置
private int markedWriterIndex;  //標記當前寫索引的位置
private int maxCapacity
; //最大容量

而支援自動擴容的部分可以由ensureWritable追蹤看到

@Override
public ByteBuf ensureWritable(int minWritableBytes) {
    if (minWritableBytes < 0) {
        throw new IllegalArgumentException(String.format(
                "minWritableBytes: %d (expected: >= 0)", minWritableBytes));
    }
    ensureWritable0(minWritableBytes);
    return this;
}

final void ensureWritable0(int minWritableBytes) {
    ensureAccessible();
    if (minWritableBytes <= writableBytes()) {
        return;
    }

    if (minWritableBytes > maxCapacity - writerIndex) {
        throw new IndexOutOfBoundsException(String.format(
                "writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
                writerIndex, minWritableBytes, maxCapacity, this));
    }

    // Normalize the current capacity to the power of 2.
    int newCapacity = alloc().calculateNewCapacity(writerIndex + minWritableBytes, maxCapacity);

    // Adjust to the new capacity.
    capacity(newCapacity);
}

在AbstractByteBufAllocator中

static final int CALCULATE_THRESHOLD = 1048576 * 4; // 4 MiB page
/**
 * 計算新容量
 */
@Override
public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
    if (minNewCapacity < 0) {
        throw new IllegalArgumentException("minNewCapacity: " + minNewCapacity + " (expected: 0+)");
    }
    if (minNewCapacity > maxCapacity) {
        throw new IllegalArgumentException(String.format(
                "minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
                minNewCapacity, maxCapacity));
    }
    final int threshold = CALCULATE_THRESHOLD; // 4 MiB page

    if (minNewCapacity == threshold) {
        return threshold;
    }

    // If over threshold, do not double but just increase by threshold.
    if (minNewCapacity > threshold) {
        int newCapacity = minNewCapacity / threshold * threshold;
        if (newCapacity > maxCapacity - threshold) {
            newCapacity = maxCapacity;
        } else {
            newCapacity += threshold;
        }
        return newCapacity;
    }

    // Not over threshold. Double up to 4 MiB, starting from 64.
    int newCapacity = 64;
    while (newCapacity < minNewCapacity) {
        newCapacity <<= 1;
    }

    return Math.min(newCapacity, maxCapacity);
}

這個newCapacity就是擴容的新容量,所以我們一般不需要擔心ByteBuf容