看完的给提点建议
netty 封装了java自带的 buffer,因为buffer上的一些缺现
netty4.0
byteBuf的指针
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
一陀。我的天。一个个分析吧.
一、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
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
private final ByteBufAllocator alloc;
private final boolean direct;
private final List
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
return new ArrayList
}
//添加一个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
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
ensureAccessible();
if (components.isEmpty()) {
return EMPTY_ITERATOR;
}
return new CompositeByteBufIterator();
}
//返回指定位置 到长度的,,如果 长度跨 对象的话。会把这两个bytebuf都返回。bytebuf中的所有的数据返回(slice是返回未读的,但是不好使,后面在看)
public List
checkIndex(offset, length);
if (length == 0) {
return Collections.emptyList();
}
int componentId = toComponentIndex(offset);
List
// 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
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
@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;
}