PoolSubPage内部数据结构分析
final class PoolSubpage<T> {
final PoolChunk<T> chunk; // 所属的PoolChunk
private final int memoryMapIdx; // 在memoryMap的索引 id memoryMap[id]
private final int runOffset; // 在PoolChunk的运行时内存偏移量
private final int pageSize; // pageSize
private final long[] bitmap;
PoolSubpage<T> prev;
PoolSubpage<T> next;
boolean doNotDestroy;
int elemSize;
private int maxNumElems;
private int bitmapLength; // bitmap中实际使用的长度
private int nextAvail; //下一个可分配的elemSize块
private int numAvail; //目前可用的elemSize块数量。
// TODO: Test if adding padding helps under contention
//private long pad0, pad1, pad2, pad3, pad4, pad5, pad6, pad7;
/** Special constructor that creates a linked list head */
PoolSubpage(int pageSize) {
chunk = null;
memoryMapIdx = -1;
runOffset = -1;
elemSize = -1;
this.pageSize = pageSize;
bitmap = null;
}
PoolSubpage(PoolChunk<T> chunk, int memoryMapIdx, int runOffset, int pageSize, int elemSize) {
this.chunk = chunk;
this.memoryMapIdx = memoryMapIdx;
this.runOffset = runOffset;
this.pageSize = pageSize;
bitmap = new long[pageSize >>> 10]; // pageSize / 16 / 64
init(elemSize);
}
PoolSubpage由大小相等的elemSize组成,elemSize表示第一次在该PoolSubpage申请内存的大小,用bitmap来表示每一个elemSize是否被占用。
void init(int elemSize) {
doNotDestroy = true;
this.elemSize = elemSize;
if (elemSize != 0) {
maxNumElems = numAvail = pageSize / elemSize;
nextAvail = 0;
bitmapLength = maxNumElems >>> 6; // @1
if ((maxNumElems & 63) != 0) { //@2
bitmapLength ++;
}
for (int i = 0; i < bitmapLength; i ++) {
bitmap[i] = 0;
}
}
addToPool();
}
这里主要是来计算maxNumElems,numAvail。bitmapLenth为bitmap实际需要的长度。其实等于 maxNumElems /64 = maxNumElems >>>6,代码@2,如果maxNumElems如果小于64,那么maxNumElems>>>6则等为0,所以需要加一。
private void addToPool() {
PoolSubpage<T> head = chunk.arena.findSubpagePoolHead(elemSize);
assert prev == null && next == null;
prev = head;
next = head.next;
next.prev = this;
head.next = this;
}