Netty ByteBuf分析

看完的给提点建议


netty 封装了java自带的 buffer,因为buffer上的一些缺现

netty4.0


byteBuf的指针

Netty ByteBuf分析_第1张图片

readerIndex:读索引

writerindex:写索引


这张图里还缺少一个起始位0,和最大位maxCapacity

0到readerIndex为已读区,

readerIndex到writerindex为未读区

writerindex到maxCapacity为可写区


看完后总结关于ByteBuf的实现,先总结束一下

ByteBuf其实就是封装 了byte数组或ByteBuffer,为自己增加了一个读写索引。

ByteBuf的零拷贝,就是直接使用byte数组或ByteBuffer,将多个byte数组或ByteBuf组装成一个不需要拷贝,只需要将其封装 成CompositeByteBuf(聚合),每个数组都是单独存在,下面有具体看代码

ByteBuf的堆缓冲区使用byte数组实现

ByteBuf的直接内存使用nio提供的ByteBuffer实现

由于堆缓冲和直接内存都是单独存在,每次都需要创建新的影响性能,还提供了池缓冲区,由一个chunk管理,每次创建通过Recycler抽象类创建 

还有一个UnpooledUnsafeDirectByteBuf,这个是使用内存地指操 作的。具体的没肿么看。里面用的都是unsafe.


下面撸代码


分析一下Netty的byteBuf


Netty ByteBuf分析_第2张图片


一陀。我的天。一个个分析吧.

一、AbstractByteBuf继承了ByteBuf


常量

    int readerIndex;     //读索引
    int writerIndex;     //写索引
    private int markedReaderIndex; // 类似bytebuffer中的mark 用于恢复读索引位
    private int markedWriterIndex;  // 同上恢复写索引位置
    private int maxCapacity;  //缓冲区最大值
   private SwappedByteBuf swappedBuf;//返回一个带排序的

//构造方法传入缓冲区最大长度

 protected AbstractByteBuf(int maxCapacity) {
        if (maxCapacity < 0) {
            throw new IllegalArgumentException("maxCapacity: " + maxCapacity + " (expected: >= 0)");
        }
        this.maxCapacity = maxCapacity;
    }

//将读写索引设置 为0

@Override
    public ByteBuf clear() {
        readerIndex = writerIndex = 0;
        return this;
    }

//是否可读可写,都是通过索引进行判断

@Override
    public boolean isReadable() {
        return writerIndex > readerIndex;
    }


    @Override
    public boolean isReadable(int numBytes) {
        return writerIndex - readerIndex >= numBytes;
    }


    @Override
    public boolean isWritable() {
        return capacity() > writerIndex;
    }


    @Override
    public boolean isWritable(int numBytes) {
        return capacity() - writerIndex >= numBytes;
    }

//下面四个方法,mark开头备份当前读写索引位置 ,reset开头,将读写索引恢复到备份时索引,主要用于回滚

@Override
    public ByteBuf markReaderIndex() {
        markedReaderIndex = readerIndex;
        return this;
    }


    @Override
    public ByteBuf resetReaderIndex() {
        readerIndex(markedReaderIndex);
        return this;
    }


    @Override
    public ByteBuf markWriterIndex() {
        markedWriterIndex = writerIndex;
        return this;
    }


    @Override
    public ByteBuf resetWriterIndex() {
        writerIndex = markedWriterIndex;
        return this;
    }


//丢弃0到readerIndex之间的已读数据

@Override
    public ByteBuf discardReadBytes() {
        ensureAccessible(); //验证缓冲区是否被释放
        if (readerIndex == 0) {//如果读索引为0则直接回返
            return this;
        }


        if (readerIndex != writerIndex) {//判断读索引与写索引是否一至
            setBytes(0, this, readerIndex, writerIndex - readerIndex);//由子类实现,,这里应该是从读索引位置 读取到写索引的数据,向前移,具体看子类
            writerIndex -= readerIndex;//重置 写索引
            adjustMarkers(readerIndex);//重置 备份的的读写索引
            readerIndex = 0;//读索引设置 为0
        } else {
            adjustMarkers(readerIndex);
            writerIndex = readerIndex = 0;//读写索引设置 为0
        }
        return this;
    }

//类似于上面丢弃已读数据,区别读索引必须大于等于可用空间除以2,才会进行丢弃

 @Override
    public ByteBuf discardSomeReadBytes() {
        ensureAccessible();
        if (readerIndex == 0) {
            return this;
        }


        if (readerIndex == writerIndex) {
            adjustMarkers(readerIndex);
            writerIndex = readerIndex = 0;
            return this;
        }


        if (readerIndex >= capacity() >>> 1) {//判断读索引是否大余等于可用空间除以2,如果大于则丢弃已读的缓冲区
            setBytes(0, this, readerIndex, writerIndex - readerIndex);
            writerIndex -= readerIndex;
            adjustMarkers(readerIndex);
            readerIndex = 0;
        }
        return this;
    }


//重新设置 备份的读写索引,,参数decrement理解为当前读引位置 

 protected final void adjustMarkers(int decrement) {
        int markedReaderIndex = this.markedReaderIndex;
        if (markedReaderIndex <= decrement) {//备份的读索引小于等于当前索引执行
            this.markedReaderIndex = 0;//备份读索引设为0
            int markedWriterIndex = this.markedWriterIndex;//
            if (markedWriterIndex <= decrement) {//判断写索引是否小于等于当前读索引
                this.markedWriterIndex = 0;
            } else {
                this.markedWriterIndex = markedWriterIndex - decrement;//如果不小于的话。备份写索引减去当前读索引
            }
        } else {

//备份的读写索引同时减去当前的读索引,生成新的位置 
            this.markedReaderIndex = markedReaderIndex - decrement;
            markedWriterIndex -= decrement;
        }
    }


//参数:可写的字节长度,,,,验证是否允许长度写入

@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 = calculateNewCapacity(writerIndex + minWritableBytes);//计算 生成新缓冲区大小


        // Adjust to the new capacity.
        capacity(newCapacity);//设置可用缓冲区大小,具体实现看子类了
    }


//功能同上,但不会抛出异常,返回代码

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

        if (minWritableBytes <= writableBytes()) {
            return 0;
        }

        final int maxCapacity = maxCapacity();
        final int writerIndex = writerIndex();
        if (minWritableBytes > maxCapacity - writerIndex) {
            if (!force || capacity() == maxCapacity) {//可用缓冲区与最大值相等则返回1,不能扩展了
                return 1;
            }

            capacity(maxCapacity);//将可用缓冲区设置 为最大值,但还是不够用
            return 3;
        }


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


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


//计算需要赠加的缓冲大小

 private int calculateNewCapacity(int minNewCapacity) {
        final int maxCapacity = this.maxCapacity;
        final int threshold = 1048576 * 4; // 4 MiB page


        if (minNewCapacity == threshold) {//如果相等则返回threshold
            return threshold;
        }


        // If over threshold, do not double but just increase by threshold.
        if (minNewCapacity > threshold) {//判断大小是否大于4M
            int newCapacity = minNewCapacity / threshold * threshold;//能被2整除了
            if (newCapacity > maxCapacity - threshold) {//如果计算 出来的容量 大于最大值 减去4M则设置 为最大值,否则加上4M
                newCapacity = maxCapacity;
            } else {
                newCapacity += threshold;
            }
            return newCapacity;
        }


        // Not over threshold. Double up to 4 MiB, starting from 64.

//遍厉开始以64为最小值,每次乘2,直到大于需要扩展的容量 
        int newCapacity = 64;
        while (newCapacity < minNewCapacity) {
            newCapacity <<= 1;
        }
       //在这两个值里取一个小的的返回
        return Math.min(newCapacity, maxCapacity);
    }

//返回一个带顺序的byteBuf..

@Override
    public ByteBuf order(ByteOrder endianness) {
        if (endianness == null) {
            throw new NullPointerException("endianness");
        }
        if (endianness == order()) {
            return this;
        }


        SwappedByteBuf swappedBuf = this.swappedBuf;//在SwappedByteBuf 类里有一个ByteOrder控制顺序,java.nio
        if (swappedBuf == null) {
            this.swappedBuf = swappedBuf = newSwappedByteBuf();
        }
        return swappedBuf;
    }

//获得字节  以get 或 set 开始不会修改读写索引  一堆get set不看了

 @Overridea
    public byte getByte(int index) {
        checkIndex(index);//验证
        return _getByte(index);//子类来 实现的
    }

//读取一个字节,读索引加1   read和write开头会修改读写索引,一堆不看了

@Override
    public byte readByte() {
        checkReadableBytes0(1);
        int i = readerIndex;
        byte b = _getByte(i);
        readerIndex = i + 1;
        return b;
    }


该类主要封装了读写索引的操作

还有一陀方法是由子类来实现的

这里没有byte数组以及buffer,这里也交给了子类来实现


继续 读吧少年。


二 AbstractReferenceCountedByteBuf继承了上面的AbstractByteBuf


看名字是计数用的。分析一下


哈哈。这个里面的方法比较少


 private static final AtomicIntegerFieldUpdater refCntUpdater =
            AtomicIntegerFieldUpdater.newUpdater(AbstractReferenceCountedByteBuf.class, "refCnt");//定义了一个基于原子操 作的类


    private volatile int refCnt;//这个属性是用来判断是否有引用的

//构造方法,调用父类的构造器,设置 最大的的空间,并将引用数设置 为1
    protected AbstractReferenceCountedByteBuf(int maxCapacity) {
        super(maxCapacity);//
        refCntUpdater.set(this, 1);
    }

//获得引用数

 @Override
    public int refCnt() {
        return refCnt;
    }

//设置 引用数

protected final void setRefCnt(int refCnt) {
        refCntUpdater.set(this, refCnt);
    }

//计数加1

 @Override
    public ByteBuf retain() {
        return retain0(1);
    }

//计数加increment
    @Override
    public ByteBuf retain(int increment) {
        return retain0(checkPositive(increment, "increment"));//验证increment是否小于等零0,如果是则抛出异常
    }

//用于计数器运算 
    private ByteBuf retain0(final int increment) {
        int oldRef = refCntUpdater.getAndAdd(this, increment);//计数加increment  并返回原始值 
        if (oldRef <= 0 || oldRef + increment < oldRef) {//判断计数器是否小于零  或 计数器加上要增加的值  是否小于 计数器原始值 
            // Ensure we don't resurrect (which means the refCnt was 0) and also that we encountered an overflow.
            refCntUpdater.getAndAdd(this, -increment);//如果 是则将上面加的数减回来,并抛出异常
            throw new IllegalReferenceCountException(oldRef, increment);
        }
        return this;
    }

//计数减1,如果没有引用则释放对象,如果 成功释放对象则true

   @Override
    public boolean release() {
        return release0(1);
    }

//计数减decrement,如果没有引用则释放对象,如果 成功释放对象则true
    @Override
    public boolean release(int decrement) {
        return release0(checkPositive(decrement, "decrement"));
    }


    private boolean release0(int decrement) {
        int oldRef = refCntUpdater.getAndAdd(this, -decrement);//计数器加负decrement 返回原始值 
        if (oldRef == decrement) {//判断原始值 是否与参数一致,如果一致败释 放对象
            deallocate();//子类释放对象
            return true;
        } else if (oldRef < decrement || oldRef - decrement > oldRef) {//理解为参数异常时执行
            // Ensure we don't over-release, and avoid underflow.
            refCntUpdater.getAndAdd(this, decrement);
            throw new IllegalReferenceCountException(oldRef, decrement);
        }
        return false;
    }


 /**
     * Called once {@link #refCnt()} is equals 0.
     */
    protected abstract void deallocate();//子类需要进行释放对象


终 于看完了。这个类主要就是一个引用的计数器。用来判断是否要释放对象


三.CompositeByteBuf继承了AbstractReferenceCountedByteBuf

瞄了一眼。又是一堆代码。

查了一下,这是一个复合缓冲区。有多个缓冲区合 并而来


//这几个变量在底下看吧

private static final ByteBuffer EMPTY_NIO_BUFFER = Unpooled.EMPTY_BUFFER.nioBuffer();
    private static final Iterator EMPTY_ITERATOR = Collections.emptyList().iterator();

    private final ByteBufAllocator alloc;
    private final boolean direct;
    private final List components;
    private final int maxNumComponents;

    private boolean freed;


 public CompositeByteBuf(ByteBufAllocator alloc, boolean direct, int maxNumComponents) {
        super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);//最大缓冲区值  Integer.MAX_VALUE
        if (alloc == null) {
            throw new NullPointerException("alloc");
        }
        this.alloc = alloc;
        this.direct = direct;
        this.maxNumComponents = maxNumComponents;
        components = newList(maxNumComponents);//初始化。list集合 初始最大16 ,,将所有的ByteBuf放到这里,处理一堆 
    }


CompositeByteBuf(
            ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf[] buffers, int offset, int len) {
        super(AbstractByteBufAllocator.DEFAULT_MAX_CAPACITY);
        if (alloc == null) {
            throw new NullPointerException("alloc");
        }
        if (maxNumComponents < 2) {
            throw new IllegalArgumentException(
                    "maxNumComponents: " + maxNumComponents + " (expected: >= 2)");
        }


        this.alloc = alloc;
        this.direct = direct;
        this.maxNumComponents = maxNumComponents;
        components = newList(maxNumComponents);//到这跟 上面一样的


        addComponents0(false, 0, buffers, offset, len);//初始化components 
        consolidateIfNeeded();//检查是否需要合 并成一个Component
        setIndex(0, capacity());//设置 读写索引
    }

//返回一个list集合 

private static List newList(int maxNumComponents) {
        return new ArrayList(Math.min(AbstractByteBufAllocator.DEFAULT_MAX_COMPONENTS, maxNumComponents));
    }

//添加一个bytebuf到集合 中 .....下面还有几个根据数组添加buffer和Iterable集合添加bytebuf不一个个写了

 public CompositeByteBuf addComponent(ByteBuf buffer) {
        return addComponent(false, buffer);
    }


//这个方法也有一堆,参数不一样,验证不一样

public CompositeByteBuf addComponent(boolean increaseWriterIndex, ByteBuf buffer) {
        checkNotNull(buffer, "buffer");//检查buffer是否为空
        addComponent0(increaseWriterIndex, components.size(), buffer);//将buffer添加到集合 中
        consolidateIfNeeded();//判断集合 是否超过最大值 ,如果超过,则将集合 中的buffer合 并为一个
        return this;
    }


//基本上添加的时候 都会调用这个方法

 private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
        assert buffer != null;//buffer  如果为null 则抛出异常
        boolean wasAdded = false;//是否需要buffer的引用减一
        try {
            checkComponentIndex(cIndex);//验证参数


            int readableBytes = buffer.readableBytes();//写索引到读索引的距离


            // No need to consolidate - just add a component to the list.
            @SuppressWarnings("deprecation")
            Component c = new Component(buffer.order(ByteOrder.BIG_ENDIAN).slice());//创建一个Component 其中的byteBuf属性为 参数buffer的索引到写索引之中间的内容 
            if (cIndex == components.size()) {//验证添加的元素的位置 是否与集合 长度一至,如果一致则在集合 中添加上面创建的Component 
                wasAdded = components.add(c);//添加到集合 中
                if (cIndex == 0) {//判断在集合中的位置 ,如果为0则结束位置 为可读取的长度
                    c.endOffset = readableBytes;
                } else {
                    Component prev = components.get(cIndex - 1);//获取cindex前的一个对象
                    c.offset = prev.endOffset;//将开始位置 设置 成前一个的结束位置 
                    c.endOffset = c.offset + readableBytes;//将结束位置 设置 成开始位置 加上可读区长度
                }
            } else {
                components.add(cIndex, c);//插入指定位置 
                wasAdded = true;
                if (readableBytes != 0) {
                    updateComponentOffsets(cIndex);//重写集合 中所有对象的开始结束位置 
                }
            }
            if (increaseWriterIndex) {//是否需要修改写索引位置 
                writerIndex(writerIndex() + buffer.readableBytes());
            }
            return cIndex;
        } finally {
            if (!wasAdded) {//如果 添加失败则修buffer引用数减1
                buffer.release();
            }
        }
    }

//添加一堆buffer到集合 中,就是轮循调用上面的单个添加,不解释 

 private int addComponents0(boolean increaseWriterIndex, int cIndex, ByteBuf[] buffers, int offset, int len) {
        checkNotNull(buffers, "buffers");
        int i = offset;
        try {
            checkComponentIndex(cIndex);


            // No need for consolidation
            while (i < len) {
                // Increment i now to prepare for the next iteration and prevent a duplicate release (addComponent0
                // will release if an exception occurs, and we also release in the finally block here).
                ByteBuf b = buffers[i++];
                if (b == null) {
                    break;
                }
                cIndex = addComponent0(increaseWriterIndex, cIndex, b) + 1;
                int size = components.size();
                if (cIndex > size) {
                    cIndex = size;
                }
            }
            return cIndex;
        } finally {
            for (; i < len; ++i) {
                ByteBuf b = buffers[i];
                if (b != null) {
                    try {
                        b.release();
                    } catch (Throwable ignored) {
                        // ignore
                    }
                }
            }
        }
    }

//添加一堆bytebuf到集合中,参数类型 跟 上面不一样,不解释  

 public CompositeByteBuf addComponents(int cIndex, Iterable buffers) {
        addComponents0(false, cIndex, buffers);
        consolidateIfNeeded();
        return this;
    }

//这个方法上面有调用,如果 集合的长度大于最大的长度,则将集合 中所有的bytebuf合 并成一个放到集合 中,,这个没啥 要说的

 private void consolidateIfNeeded() {
        // Consolidate if the number of components will exceed the allowed maximum by the current
        // operation.
        final int numComponents = components.size();
        if (numComponents > maxNumComponents) {
            final int capacity = components.get(numComponents - 1).endOffset;


            ByteBuf consolidated = allocBuffer(capacity);


            // We're not using foreach to avoid creating an iterator.
            for (int i = 0; i < numComponents; i ++) {
                Component c = components.get(i);
                ByteBuf b = c.buf;
                consolidated.writeBytes(b);
                c.freeIfNecessary();
            }
            Component c = new Component(consolidated);
            c.endOffset = c.length;
            components.clear();
            components.add(c);
        }
    }

//集除指定位置 的bytebuf

 public CompositeByteBuf removeComponent(int cIndex) {
        checkComponentIndex(cIndex);//验证参数
        Component comp = components.remove(cIndex);//从集合 中移除
        comp.freeIfNecessary();//将bytebuf释 放
        if (comp.length > 0) {//如果 长度大于零,需要将后集合 后面的开始与结束位重置 
            // Only need to call updateComponentOffsets if the length was > 0
            updateComponentOffsets(cIndex);
        }
        return this;
    }

//方法体不写了,跟 上面一样,移除集合 中指定的位置 ,到numComponents长度的butebuf

public CompositeByteBuf removeComponents(int cIndex, int numComponents)

//返回当前集合 的Iterator

@Override
    public Iterator iterator() {
        ensureAccessible();
        if (components.isEmpty()) {
            return EMPTY_ITERATOR;
        }
        return new CompositeByteBufIterator();
    }

//返回指定位置 到长度的,,如果 长度跨 对象的话。会把这两个bytebuf都返回。bytebuf中的所有的数据返回(slice是返回未读的,但是不好使,后面在看)

 public List decompose(int offset, int length) {
        checkIndex(offset, length);
        if (length == 0) {
            return Collections.emptyList();
        }


        int componentId = toComponentIndex(offset);
        List slice = new ArrayList(components.size());


        // The first component
        Component firstC = components.get(componentId);
        ByteBuf first = firstC.buf.duplicate();
        first.readerIndex(offset - firstC.offset);


        ByteBuf buf = first;
        int bytesToSlice = length;
        do {
            int readableBytes = buf.readableBytes();
            if (bytesToSlice <= readableBytes) {
                // Last component
                buf.writerIndex(buf.readerIndex() + bytesToSlice);
                slice.add(buf);
                break;
            } else {
                // Not the last component
                slice.add(buf);
                bytesToSlice -= readableBytes;
                componentId ++;


                // Fetch the next component.
                buf = components.get(componentId).buf.duplicate();
            }
        } while (bytesToSlice > 0);


        // Slice all components because only readable bytes are interesting.
        for (int i = 0; i < slice.size(); i ++) {
            slice.set(i, slice.get(i).slice());
        }


        return slice;
    }


下面还有一些转成nio中的buffer以及销毁集合 中的byteBuf这些暂不介绍,因为这个主要负责聚合 ,集合 里用的也是byteBuf所以还要看其它的子类。


四.UnpooledHeapByteBuf 继承了AbstractReferenceCountedByteBuf

基于堆内存分配的字节缓冲区


看了一遍。代码挺多,但都是重载的,主要就是动态扩展,set方法数组复制,get方法根据下标获取数组中的原素,转成nio 中的byteBuffer,使用ByteBuffer中自带的wrap进行数组的引用


这就是堆内存啊。没有基于内存池来做,所以使用的时候 每次都需要创建一个,性能没什么要求可用这个啊。


 private final ByteBufAllocator alloc;//用于内存分配的。看看是怎么分配的吧。
    byte[] array;//数组
    private ByteBuffer tmpNioBuf;//用于转换成nio.buffer


//动态扩展缓冲区大小

 @Override
    public ByteBuf capacity(int newCapacity) {
        checkNewCapacity(newCapacity);//验证参数是否正确
        int oldCapacity = array.length;
        byte[] oldArray = array;
        if (newCapacity > oldCapacity) {//如果 要扩展的长度大长老的长度时,进行复制
            byte[] newArray = allocateArray(newCapacity);//创建新的byte[]
            System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);//将第的数组复制到新的
            setArray(newArray);//将局变量重新复值
            freeArray(oldArray);//空方法
        } else if (newCapacity < oldCapacity) {
            byte[] newArray = allocateArray(newCapacity);//创建一个大小的数组
            int readerIndex = readerIndex();//获取读索引
            if (readerIndex < newCapacity) {//如果 读索引小于需要扩展的大小
                int writerIndex = writerIndex();//获取写索引
                if (writerIndex > newCapacity) {//如果 写索引大于最大扩展的大小
                    writerIndex(writerIndex = newCapacity);//给写索引赋 值 ,要扩展的大小
                }
                System.arraycopy(oldArray, readerIndex, newArray, readerIndex, writerIndex - readerIndex);//将老的数据复到新的数组上,位置 从读索引开始
            } else {
                setIndex(newCapacity, newCapacity);//如果 读索引小于扩展的大小则不进行复制
            }
            setArray(newArray);
            freeArray(oldArray);
        }
        return this;
    }

//set数据,进行数据复制

 @Override
    public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
        checkSrcIndex(index, length, srcIndex, src.length);
        System.arraycopy(src, srcIndex, array, index, length);
        return this;
    }

//获取nio.byteBuffer

@Override
    public ByteBuffer nioBuffer(int index, int length) {
        ensureAccessible();
        return ByteBuffer.wrap(array, index, length).slice();//调用byteBuffer中的方法进行数组复制
    }


五、UnpooledDirectByteBuf继承了AbstractReferenceCountedByteBuf

直接内存,就是使用java自带的nio.ByteBuffer


private final ByteBufAllocator alloc;//内存分配


    private ByteBuffer buffer;//nio.buffer读写操 作
    private ByteBuffer tmpNioBuf;//理解为上面的副本。独立索引,内容 可见
    private int capacity;//最大容量 
    private boolean doNotFree;//用来判断是否释放引用的

//动态扩展,,基于nio.ByteBuffer做的。读写索引还用是ByteBuf的

@Override
    public ByteBuf capacity(int newCapacity) {
        checkNewCapacity(newCapacity);
int readerIndex = readerIndex();
        int writerIndex = writerIndex();


        int oldCapacity = capacity;
        if (newCapacity > oldCapacity) {
            ByteBuffer oldBuffer = buffer;
            ByteBuffer newBuffer = allocateDirect(newCapacity);//创建一个bytebuffer
            oldBuffer.position(0).limit(oldBuffer.capacity());//设置位置 及限制
            newBuffer.position(0).limit(oldBuffer.capacity());//设置位置 及限制
            newBuffer.put(oldBuffer);//数据复制
            newBuffer.clear();//清除位置 
            setByteBuffer(newBuffer);//赋 值 
        } else if (newCapacity < oldCapacity) {
            ByteBuffer oldBuffer = buffer;
            ByteBuffer newBuffer = allocateDirect(newCapacity);
            if (readerIndex < newCapacity) {
                if (writerIndex > newCapacity) {
                    writerIndex(writerIndex = newCapacity);
                }
                oldBuffer.position(readerIndex).limit(writerIndex);
                newBuffer.position(readerIndex).limit(writerIndex);
                newBuffer.put(oldBuffer);
                newBuffer.clear();
            } else {
                setIndex(newCapacity, newCapacity);
            }
            setByteBuffer(newBuffer);
        }
        return this;
    }


六、UnpooledUnsafeDirectByteBuf继承了AbstractReferenceCountedByteBuf

基于内存地址的直接缓冲区,自己理解 就是通过unsafe直接对内存地址操 作,方法与UnpooledDirectByteBuf基本相同,除了存值 与取值 


 final void setByteBuffer(ByteBuffer buffer, boolean tryFree) {
        if (tryFree) {
            ByteBuffer oldBuffer = this.buffer;
            if (oldBuffer != null) {
                if (doNotFree) {
                    doNotFree = false;
                } else {
                    freeDirect(oldBuffer);
                }
            }
        }
        this.buffer = buffer;
        memoryAddress = PlatformDependent.directBufferAddress(buffer);//将buffer的地址取出,
        tmpNioBuf = null;
        capacity = buffer.remaining();
    }

//根据内存地址通过unsafe获取值 。

@Override
    protected byte _getByte(int index) {
        return UnsafeByteBufUtil.getByte(addr(index));
    }


long addr(int index) {
        return memoryAddress + index;
    }


七、PooledByteBuf继承了AbstractReferenceCountedByteBuf

内存池缓冲区 抽象类

看了一遍主要是PoolChunk 对象用来管理


PoolChunk 这个东东。代码太多了。理解一下看这里   http://blog.csdn.net/zero__007/article/details/73294783


private final Recycler.Handle recyclerHandle;


    protected PoolChunk chunk;//管理page,内存区域
    protected long handle;//应该是位置 
    protected T memory;//bytebuf
    protected int offset;//开始位置 
    protected int length;//长度
    int maxLength;//总长度
    PoolThreadCache cache;//看名字是缓存线程。不知道 干啥 的
    private ByteBuffer tmpNioBuf;//应该是复制出来的bytebuff
    private ByteBufAllocator allocator;//接口

//设置 大小

 @Override
    public final ByteBuf capacity(int newCapacity) {
        checkNewCapacity(newCapacity);


        // If the request capacity does not require reallocation, just update the length of the memory.
        if (chunk.unpooled) {
            if (newCapacity == length) {
                return this;
            }
        } else {
            if (newCapacity > length) {
                if (newCapacity <= maxLength) {
                    length = newCapacity;
                    return this;
                }
            } else if (newCapacity < length) {
                if (newCapacity > maxLength >>> 1) {//一堆if,自己看吧,就是判断 大小用的
                    if (maxLength <= 512) {
                        if (newCapacity > maxLength - 16) {
                            length = newCapacity;

//所有的if通过设置 读写索引
                            setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
                            return this;
                        }
                    } else { // > 512 (i.e. >= 1024)
                        length = newCapacity;
                        setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
                        return this;
                    }
                }
            } else {
                return this;
            }
        }


        // Reallocation required.
        chunk.arena.reallocate(this, newCapacity, true);//复制
        return this;
    }


八、PooledDirectByteBuf extends PooledByteBuf

池直接内存缓冲区,与非池直接内存缓冲区区别在余创建 与销毁


PooledHeapByteBuf,PooledUnsafeDirectByteBuf类似,都是通过接口创建 非池缓冲区由chunk管理


//创建时通过Recycler创建 

 private static final Recycler RECYCLER = new Recycler() {
        @Override
        protected PooledDirectByteBuf newObject(Handle handle) {
            return new PooledDirectByteBuf(handle, 0);
        }
    };


    static PooledDirectByteBuf newInstance(int maxCapacity) {
        PooledDirectByteBuf buf = RECYCLER.get();//通过上面的创建
        buf.reuse(maxCapacity);
        return buf;
    }





你可能感兴趣的:(netty)