netty学习笔记07——缓冲区Buffer
基本介绍
缓冲区Buffer,缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个容器对象(含数组),该对象提供了一组方法,可以更轻松地使用内存块,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况。Channel提供从文件、网络读取数据 渠道,但是读取或写入的数据都必须经由Buffer。
重要参数
- capacity 容量,在创建buffer的时候就创建好的,无法进行更改,当写入或者读取超出这个限制的时候,会抛出异常
- limit 当前可读写的限制,写模式下就是还剩下多少空间,读模式下就是还可以读多少数据
- position 当前的位置
- mark 标记
相关API阅读
构造buffer
构造器
Buffer(int mark, int pos, int lim, int cap) {//这个构造器是包私有的,不允许直接通过构造器创建Buffer对象
if (cap < 0)//基本的容量判断
throw new IllegalArgumentException("Negative capacity: " + cap);
this.capacity = cap;//根据输入的cap进行赋值
limit(lim);//进行limit赋值
position(pos);//
if (mark >= 0) {
if (mark > pos)
throw new IllegalArgumentException("mark > position: ("
+ mark + " > " + pos + ")");
this.mark = mark;
}
}
limit(int newlimit)
public final Buffer limit(int newLimit) {
if ((newLimit > capacity) || (newLimit < 0))//参数校验
throw new IllegalArgumentException();
limit = newLimit;//更新limit
if (position > limit) position = limit;//如果limit比position小,就更新position
if (mark > limit) mark = -1;//如果limit比mark小,就更新mark
return this;
}
position(int newPosition)
public final Buffer position(int newPosition) {
if ((newPosition > limit) || (newPosition < 0))//参数校验
throw new IllegalArgumentException();
position = newPosition;//更新position
if (mark > position) mark = -1;
return this;
}
从以上的方法可以看出
- 首先无法通过构造器创建Buffer
- 还对limit和position进行校验和赋值
Buffer的创建
既然无法进行直接构造器创建buffer,那么buffer应该怎么创建呢?
常见的用法如下所示:
Buffer buffer = ByteBuffer.allocate(1024);
即通过Buffer的实现类进行分配一个buffer,进入ByteBuffer看看allocate方法做了什么
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
进行了两步操作:
- 校验capacity
- 调用HeapByteBuffer构造器
Buffer有三种模式,一个是直接分配在堆上,一个是分配在直接内存上,分配在堆上就受GC控制。这个HeapByteBuffer就是一个分配在堆上的子类
进入HeapByteBuffer的构造器:
HeapByteBuffer(int cap, int lim) { // package-private
super(-1, 0, lim, cap, new byte[cap], 0);
/*
hb = new byte[cap];
offset = 0;
*/
}
直接复用了父类(ByteBuffer)的构造器
ByteBuffer(int mark, int pos, int lim, int cap, // package-private
byte[] hb, int offset)
{
super(mark, pos, lim, cap);
this.hb = hb;
this.offset = offset;
}
其中super是父类Buffer的构造器,在前一节已经提到过了,hb即对象的容器,ByteBuffer将数据维护在这里。offset即数据在hb中的偏移量。
flip()方法行为
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
将limit限制为当前的position,position归0
Get()和Put()行为
final int nextGetIndex() { // package-private
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
final int nextPutIndex() { // package-private
if (position >= limit)
throw new BufferOverflowException();
return position++;
}
读取写入自增长