关键属性
// 所属chunk
protected PoolChunk<T> chunk;
// 在chunk中内存地址的偏移
protected long handle;
//
protected T memory;
protected int offset;
// 实际当时申请的内存大小
protected int length;
// 实际底层返回的最大可用的内存大小
int maxLength;
// 跟线程绑定的本地缓存
PoolThreadCache cache;
//
private ByteBuffer tmpNioBuf;
扩容
public final ByteBuf capacity(int newCapacity) {
ensureAccessible();
// 如果是非池化,且容量不变,那么直接返回,没有扩容的需要
if (chunk.unpooled) {
if (newCapacity == length) {
return this;
}
} else {
// 如果是池化,且新的容量要比之前申请的大,但还没有超过底层最大所能容纳空间,那么只需要
// 更新length,返回即可。
if (newCapacity > length) {
if (newCapacity <= maxLength) {
length = newCapacity;
return this;
}
// 如果新的容量比之前申请的小,说明是缩容的动作
} else if (newCapacity < length) {
// 如果新的容量要大于max的一半,起码small类型那边就不用动了,因为small是翻倍递增的
if (newCapacity > maxLength >>> 1) {
// 如果是tiny类型
if (maxLength <= 512) {
// 首先要明确,tiny是16B递增的,只要在16的范围内浮动就可以复用当前的空间
// 想一想,假如现在分配的tiny块是498的max,只要新的容量在498-16到498的范围
// 内,那么就只需要更新index就好
if (newCapacity > maxLength - 16) {
length = newCapacity;
setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
return this;
}
} else { // > 512 (i.e. >= 1024)
// 如前small所述
length = newCapacity;
setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
return this;
}
}
} else {
return this;
}
}
// Reallocation required.
// 到这里说明前面的努力全部失败,那么去arena实际去找更合适的内存区域
chunk.arena.reallocate(this, newCapacity, true);
return this;
}
网友评论