ByteBuffer源码解读
javaNIO中涉及缓存的类有很多,除了boolean类型外,每种基本类型都有对应的缓冲区类,包括CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer和ShortBuffer。
所有的缓存区都有以下属性:
- 容量(capacity):表示该缓存区可以保存多少数据。
- 极限(limit):表示缓存区的当前终点,是逻辑终点,物理终点应该是capacity,不能对缓冲区中超过极限的区域进行写操作。极限值是可以修改的,所以可以更加灵活操作缓存区。
- 位置(position):表示缓存区中下一个读写单元的位置,每次读写缓冲区的数据时,都会改变该值,为下一次读写数据做准备。
以上提到的缓冲区类都是能够返回自身实例的静态工厂方法allocate(intcapacity)。本次通过分析ByteBuffer源码,分析缓存工作过程。与ByteBuffer有关的还有两个类:HeapByteBuffer和Buffer。Buffer是ByteBuffer的父抽象类,定义了mark,position,limit,capacity四个属性。ByteBuffer是针对Byte类型的缓存类,定义了hb属性,类型为byte[]。HeapByteBuffer是ByteBuffer的实现类。
ByteBuffer初始化过程:
1:allocate分配函数中返回的是ByteBuffer的子类HeapByteBuffer的对象。
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer>{
public static ByteBuffer allocate(int capacity) {
if (capacity < 0)
throw new IllegalArgumentException();
return new HeapByteBuffer(capacity, capacity);
}
}
2:HeapByteBuffer构造函数如下:cap=capacity;lim=capacity;仍然是调用父类,也就是ByteBuffer的构造函数。
class HeapByteBuffer extends ByteBuffer { HeapByteBuffer(int cap, int lim) { super(-1, 0, lim, cap, new byte[cap], 0); } }
3:ByteBuffer构造函数如下:mark=-1;pos=0;lim=lim=capacity;cap=cap=capacity;hb=new byte[cap],offset=0;,ByteBuffer仍然调用父类,也就是Buffer的构造函数后,初始化hb和offset。
public abstract class ByteBuffer extends Buffer implements Comparable<ByteBuffer> { ByteBuffer(int mark, int pos, int lim, int cap,byte[] hb, int offset){ super(mark, pos, lim, cap); this.hb = hb; this.offset = offset; } }
4:Buffer构造函数如下:mark=-1;lim=lim=lim=capacity;pos=0;cap=cap=cap=capacity
Buffer(int mark, int pos, int lim, int cap) { if (cap < 0) throw new IllegalArgumentException("Negative capacity: " + cap); this.capacity = cap; //初始化capacity limit(lim); //检查lim position(pos); //检查position if (mark >= 0) { //检查mark if (mark > pos) throw new IllegalArgumentException("mark > position: ("+ mark + " > " + pos + ")"); this.mark = mark; } }
5:limit检查函数
public final Buffer limit(int newLimit) { if ((newLimit > capacity) || (newLimit < 0)) //limit不能设置大于capacity或者小于0 throw new IllegalArgumentException(); limit = newLimit; //初始化limit属性 if (position > limit) position = limit; //如果当前position大于limit,position=limit if (mark > limit) mark = -1; //如果mark大于limit,mark=-1 return this; }
6:position检查函数
public final Buffer position(int newPosition) { if ((newPosition > limit) || (newPosition < 0)) //position不能设置大于limit或者小于0 throw new IllegalArgumentException(); position = newPosition; //初始化position if (mark > position) mark = -1; //如果mark>position,mark=-1 return this; }
初始化完成后,HeapByteBuffer存储过程源码如下:
存过程:
public ByteBuffer put(byte x) { hb[ix(nextPutIndex())] = x; return this; } public ByteBuffer put(int i, byte x) { hb[ix(checkIndex(i))] = x; return this; }
final int nextPutIndex() {
if (position >= limit)//如果当前位置值或等于限制值,则表示没有空间能使用
throw new BufferOverflowException();
return position++; //否则返回当前空的一位空间
}
final int nextPutIndex(int nb) {
if (limit - position < nb) //想要存储的位置只能在当前位置值和限制值中间,否则报错
throw new BufferOverflowException();
int p = position;
position += nb; //返回要存储的位置
return p;
}
protected int ix(int i) {
return i + offset; //i+偏移位
}
取过程如下,与存过程类似:
public byte get() { return hb[ix(nextGetIndex())]; } public byte get(int i) { return hb[ix(checkIndex(i))]; }
final int nextGetIndex() {
if (position >= limit)
throw new BufferUnderflowException();
return position++;
}
final int nextGetIndex(int nb) {
if (limit - position < nb)
throw new BufferUnderflowException();
int p = position;
position += nb;
return p;
}
缓存函数:
1.Buffer抽象类下的clear()
public final Buffer clear() { position = 0; //位置设置为0 limit = capacity; //限制设置为当前容量值 mark = -1; //mark为-1 return this; }
2.Buffer抽象类下的flip()
public final Buffer flip() { limit = position; //限制设置为当前位置 position = 0; //当前位置设置为0 mark = -1; //mark=-1 return this; }
3.Buffer抽象类下的rewind()
public final Buffer rewind() { position = 0; //当前位置为0 mark = -1; //mark为-1 return this; }