看完的给提点建议
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",<