Netty源码分析 - ByteBuf

系列

Netty源码分析 - Bootstrap服务端
Netty源码分析 - Bootstrap客户端
netty源码分析 - ChannelHandler
netty源码分析 - EventLoop类关系
netty源码分析 - register分析
Netty源码分析 - NioEventLoop事件处理
netty源码分析 - accept过程分析
Netty源码分析 - ByteBuf
Netty源码分析 - 粘包和拆包问题


开篇

这篇文章的用于阐述下Netty当中ByteBuf的基本类型,以及一些对应的内部分配器,算作一片入门的文章,阅读起来较为简单。

Pooled 和 Unpooled

  • Pooled池化内存分配每次从预先分配好的一块内存取一段连续内存封装成ByteBuf提供给应用程序。

  • Unpooled非池化每次进行内存分配的时候调用系统API向操作系统申请一块内存。

Unsafe 和 非Unsafe

  • Unsafe直接获取ByteBuf在JVM内存地址调用JDK的Unsafe进行读写操作,通过ByteBuf分配内存首地址和当前指针基于内存偏移地址获取值。
  • 非Unsafe不依赖JDK的Unsafe对象,通过内存数组和索引获取值。

Heap和Direct

  • Heap在堆上进行内存分配,分配内存需要被GC管理,无需手动释放内存,依赖底层byte数组,
  • Direct调用JDK的API进行内存分配,分配内存不受JVM控制最终不会参与GC过程,需要手动释放内存避免造成内存无法释放,依赖DirectByteBuffer对象内存


ByteBuf类关系图

PooledByteBuf
  • PooledByteBuf情况下分为Heap和Direct两种。



UnPooledByteBuf

  • UnPooledByteBuf的buf同样分为Heap和Direct两种。



CompositeByteBuf

  • CompositeByteBuf只有一种分类。


ByteBuf结构

*      +-------------------+------------------+------------------+
*      | discardable bytes |  readable bytes  |  writable bytes  |
*      +-------------------+------------------+------------------+
*      |                   |                  |                  |
*      0      <=      readerIndex   <=   writerIndex    <=    capacity
public abstract class AbstractByteBuf extends ByteBuf {
    int readerIndex;
    int writerIndex;
    private int markedReaderIndex;
    private int markedWriterIndex;
    private int maxCapacity;
}
  • ByteBuf的数据结构如上图所示。
  • int readerIndex; //读索引
  • int writerIndex; //写索引
  • private int markedReaderIndex;//标记读索引
  • private int markedWriterIndex;//标记写索引
  • private int maxCapacity;//缓冲区的最大容量


ByteBuf类依赖图

UnpooledHeapByteBuf

UnpooledHeapByteBuf
public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {

    private final ByteBufAllocator alloc;
    byte[] array;
    private ByteBuffer tmpNioBuf;

    protected UnpooledHeapByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
        this(alloc, new byte[initialCapacity], 0, 0, maxCapacity);
    }

    private UnpooledHeapByteBuf(
            ByteBufAllocator alloc, byte[] initialArray, int readerIndex, int writerIndex, int maxCapacity) {

        super(maxCapacity);
        this.alloc = alloc;
        setArray(initialArray);
        setIndex(readerIndex, writerIndex);
    }

    private void setArray(byte[] initialArray) {
        array = initialArray;
        tmpNioBuf = null;
    }
}
  • UnpooledHeapByteBuf的内部存储结构是byte[] array数组。


UnpooledDirectByteBuf

UnpooledDirectByteBuf
public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
    private final ByteBufAllocator alloc;
    private ByteBuffer buffer;
    private ByteBuffer tmpNioBuf;
    private int capacity;
    private boolean doNotFree;

    protected UnpooledDirectByteBuf(ByteBufAllocator alloc, int initialCapacity, int maxCapacity) {
        super(maxCapacity);
       
        this.alloc = alloc;
        setByteBuffer(ByteBuffer.allocateDirect(initialCapacity));
    }

    private void setByteBuffer(ByteBuffer buffer) {
        ByteBuffer oldBuffer = this.buffer;
        if (oldBuffer != null) {
            if (doNotFree) {
                doNotFree = false;
            } else {
                freeDirect(oldBuffer);
            }
        }

        this.buffer = buffer;
        tmpNioBuf = null;
        capacity = buffer.remaining();
    }
}
  • UnpooledDirectByteBuf的ByteBuffer通过JDK创建的直接内测,即通过ByteBuffer.allocateDirect(initialCapacity)进行创建。


PooledDirectByteBuf

PooledDirectByteBuf


PooledHeapByteBuf

PooledHeapByteBuf


CompositeByteBuf

CompositeByteBuf
public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable {

    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;

    CompositeByteBuf(
            ByteBufAllocator alloc, boolean direct, int maxNumComponents, ByteBuf[] buffers, int offset, int len) {
        super(Integer.MAX_VALUE);
        this.alloc = alloc;
        this.direct = direct;
        this.maxNumComponents = maxNumComponents;
        components = newList(maxNumComponents);

        addComponents0(false, 0, buffers, offset, len);
        // 是否需要进行扩容
        consolidateIfNeeded();
        setIndex(0, capacity());
    }

    // 添加ByteBuf到components当中
    private int addComponent0(boolean increaseWriterIndex, int cIndex, ByteBuf buffer) {
        assert buffer != null;
        boolean wasAdded = false;
        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());
            if (cIndex == components.size()) {
                wasAdded = components.add(c);
                if (cIndex == 0) {
                    // //如果是第一个buffer,则该Component的endOffset为buffer的大小。
                    c.endOffset = readableBytes;
                } else {
                    // 如果不是第一个buffer,则该buffer的offset为上一个的end
                    Component prev = components.get(cIndex - 1);
                    c.offset = prev.endOffset;
                    // 如果不是第一个buffer,则该buffer的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.release();
            }
        }
    }
  
    // 针对components判断是否需要进行扩容
    private void consolidateIfNeeded() {
        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);
        }
    }
}
  • CompositeByteBuf 在聚合时使用,多个buffer合并时,不需要copy,通过
    CompositeByteBuf 可以把需要合并的bytebuf 组合起来,对外提供统一的readindex和writerindex

  • CompositeByteBuf 里面有个ComponentList,继承ArrayList,聚合的bytebuf都放在ComponentList里面,最小容量为16。

  • CompositeByteBuf 在增加新的bytebuf后,会检查CompositeByteBuf的数组components 大小,默认大小是16,即在组合了16个bytebuf后,就要扩容了。

  • CompositeByteBuf是创建一个新的bytebuf,把数组里的16个bytebuf所有数据写到这个新创建bytebuf里,然后把旧数组清空,并把新创建的一个大的bytebuf添加到数组里。


内存分配器

ByteBufAllocator

UnpooledByteBufAllocator

UnpooledByteBufAllocator
public final class UnpooledByteBufAllocator extends AbstractByteBufAllocator {

    protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
        return PlatformDependent.hasUnsafe() ? new UnpooledUnsafeHeapByteBuf(this, initialCapacity, maxCapacity)
                : new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
    }

    protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        ByteBuf buf = PlatformDependent.hasUnsafe() ?
                UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity) :
                new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);

        return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
    }

    public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) {
        CompositeByteBuf buf = new CompositeByteBuf(this, false, maxNumComponents);
        return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
    }

    public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) {
        CompositeByteBuf buf = new CompositeByteBuf(this, true, maxNumComponents);
        return disableLeakDetector ? buf : toLeakAwareBuffer(buf);
    }
}
  • UnpooledByteBufAllocator提供newHeapBuffer、newDirectBuffer、compositeHeapBuffer等方法创建对应的ByteBuf对象。


PooledByteBufAllocator

PooledByteBufAllocator
public class PooledByteBufAllocator extends AbstractByteBufAllocator {

    protected ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena heapArena = cache.heapArena;

        ByteBuf buf;
        if (heapArena != null) {
            buf = heapArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            buf = new UnpooledHeapByteBuf(this, initialCapacity, maxCapacity);
        }

        return toLeakAwareBuffer(buf);
    }

    @Override
    protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
        PoolThreadCache cache = threadCache.get();
        PoolArena directArena = cache.directArena;

        ByteBuf buf;
        if (directArena != null) {
            buf = directArena.allocate(cache, initialCapacity, maxCapacity);
        } else {
            if (PlatformDependent.hasUnsafe()) {
                buf = UnsafeByteBufUtil.newUnsafeDirectByteBuf(this, initialCapacity, maxCapacity);
            } else {
                buf = new UnpooledDirectByteBuf(this, initialCapacity, maxCapacity);
            }
        }

        return toLeakAwareBuffer(buf);
    }
}
  • PooledByteBufAllocator的newHeapBuffer、newDirectBuffer等方法创建对应的ByteBuf对象。


参考

  • Netty之ByteBuf深入分析
  • 对于 Netty ByteBuf 的零拷贝(Zero Copy) 的理解

你可能感兴趣的:(Netty源码分析 - ByteBuf)