Repository navigation
netty eventloop pooled_direct
wangkaiwu edited this page Feb 13, 2023
·
1 revision
仅有一个默认构造
final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
private PooledUnsafeDirectByteBuf(Handle<PooledUnsafeDirectByteBuf> recyclerHandle, int maxCapacity) {
super(recyclerHandle, maxCapacity);
}
}abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
private final Handle<PooledByteBuf<T>> recyclerHandle;
protected PooledByteBuf(Handle<? extends PooledByteBuf<T>> recyclerHandle, int maxCapacity) {
super(maxCapacity);
this.recyclerHandle = (Handle<PooledByteBuf<T>>) recyclerHandle;
}
}public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
protected AbstractReferenceCountedByteBuf(int maxCapacity) {
super(maxCapacity);
}
}public abstract class AbstractByteBuf extends ByteBuf {
private int maxCapacity;
protected AbstractByteBuf(int maxCapacity) {
this.maxCapacity = maxCapacity;
}
}final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
private static final ObjectPool<PooledUnsafeDirectByteBuf> RECYCLER = ObjectPool.newPool(
new ObjectCreator<PooledUnsafeDirectByteBuf>() {
@Override
public PooledUnsafeDirectByteBuf newObject(Handle<PooledUnsafeDirectByteBuf> handle) {
// 调用构造器
return new PooledUnsafeDirectByteBuf(handle, 0);
}
});
}public abstract class ObjectPool<T> {
private static final class RecyclerObjectPool<T> extends ObjectPool<T> {
private final Recycler<T> recycler;
RecyclerObjectPool(final ObjectCreator<T> creator) {
recycler = new Recycler<T>() {
@Override
protected T newObject(Handle<T> handle) {
// 调用了上面的方法
return creator.newObject(handle);
}
};
}
}
}public abstract class Recycler<T> {
private final int maxCapacityPerThread;
private final FastThreadLocal<Stack<T>> threadLocal = new FastThreadLocal<Stack<T>>() {
};
public final T get() {
if (maxCapacityPerThread == 0) {
// 单个线程的最大容量
return newObject((Handle<T>) NOOP_HANDLE);
}
// 线程局部变量里的栈结构
Stack<T> stack = threadLocal.get();
DefaultHandle<T> handle = stack.pop();
if (handle == null) {
// 说明没有,生成一个
handle = stack.newHandle();
handle.value = newObject(handle);
}
return (T) handle.value;
}
}public abstract class ObjectPool<T> {
private static final class RecyclerObjectPool<T> extends ObjectPool<T> {
@Override
public T get() {
// 调用上面的 get 方法
return recycler.get();
}
}
}final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
static PooledUnsafeDirectByteBuf newInstance(int maxCapacity) {
// 产生一个 buffer
PooledUnsafeDirectByteBuf buf = RECYCLER.get();
// ......
return buf;
}
}abstract class PoolArena<T> implements PoolArenaMetric {
static final class DirectArena extends PoolArena<ByteBuffer> {
@Override
protected PooledByteBuf<ByteBuffer> newByteBuf(int maxCapacity) {
if (HAS_UNSAFE) {
// 调用上面的方法
return PooledUnsafeDirectByteBuf.newInstance(maxCapacity);
} else {
return PooledDirectByteBuf.newInstance(maxCapacity);
}
}
}
}abstract class PoolArena<T> implements PoolArenaMetric {
PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) {
PooledByteBuf<T> buf = newByteBuf(maxCapacity);
// TODO:
allocate(cache, buf, reqCapacity);
return buf;
}
}public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
private final PoolThreadLocalCache threadCache;
@Override
protected ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity) {
PoolThreadCache cache = threadCache.get();
PoolArena<ByteBuffer> directArena = cache.directArena;
final ByteBuf buf;
if (directArena != null) {
buf = directArena.allocate(cache, initialCapacity, maxCapacity);
} else {
// ...........
}
// TODO:
return toLeakAwareBuffer(buf);
}
}public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
@Override
public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
return newDirectBuffer(initialCapacity, maxCapacity);
}
}public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
static final int DEFAULT_MAX_CAPACITY = Integer.MAX_VALUE;
@Override
public ByteBuf directBuffer(int initialCapacity) {
return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
}
}public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
@Override
public ByteBuf ioBuffer(int initialCapacity) {
if (PlatformDependent.hasUnsafe() || isDirectBufferPooled()) {
// 支持 unsafe 且启用了 pool
return directBuffer(initialCapacity);
}
return heapBuffer(initialCapacity);
}
}public abstract class DefaultMaxMessagesRecvByteBufAllocator implements MaxMessagesRecvByteBufAllocator {
@Override
public ByteBuf allocate(ByteBufAllocator alloc) {
// TODO:
return alloc.ioBuffer(guess());
}
}通过下面的位置,确认了当 channel 收到新消息到时候,就会先分配一个 byteBuffer,大小由算法决定。
protected class NioByteUnsafe extends AbstractNioUnsafe {
@Override
public final void read() {
// ........
ByteBuf byteBuf = null;
// .........
byteBuf = allocHandle.allocate(allocator);
// .........
}
}public abstract class Recycler<T> {
private static final class DefaultHandle<T> implements Handle<T> {
Stack<?> stack;
DefaultHandle(Stack<?> stack) {
this.stack = stack;
}
@Override
public void recycle(Object object) {
Stack<?> stack = this.stack;
stack.push(this);
}
}
}abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
private void recycle() {
recyclerHandle.recycle(this);
}
}abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
protected PoolChunk<T> chunk;
protected long handle;
protected T memory;
@Override
protected final void deallocate() {
if (handle >= 0) {
final long handle = this.handle;
this.handle = -1;
memory = null;
chunk.arena.free(chunk, tmpNioBuf, handle, maxLength, cache);
chunk = null;
recycle();
}
}
}public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
private boolean handleRelease(boolean result) {
if (result) {
deallocate();
}
return result;
}
}public abstract class AbstractReferenceCountedByteBuf extends AbstractByteBuf {
@Override
public boolean release() {
// TODO:
return handleRelease(updater.release(this));
}
}public final class ReferenceCountUtil {
public static boolean release(Object msg) {
if (msg instanceof ReferenceCounted) {
return ((ReferenceCounted) msg).release();
}
return false;
}
}public final class ReferenceCountUtil {
public static void safeRelease(Object msg) {
release(msg);
}
}当buffer 写出成功后,会触发 release
public final class ChannelOutboundBuffer {
private Entry flushedEntry;
public boolean remove() {
Entry e = flushedEntry;
//........
Object msg = e.msg;
//.........
if (!e.cancelled) {
ReferenceCountUtil.safeRelease(msg);
// ........
}
//.......
return true;
}
}public abstract class AbstractByteBuf extends ByteBuf {
int readerIndex;
@Override
public byte readByte() {
int i = readerIndex;
byte b = _getByte(i);
readerIndex = i + 1;
return b;
}
}final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
private long memoryAddress;
@Override
protected byte _getByte(int index) {
return UnsafeByteBufUtil.getByte(addr(index));
}
private long addr(int index) {
// 存在一个内存基址
return memoryAddress + index;
}
}final class UnsafeByteBufUtil {
static byte getByte(long address) {
return PlatformDependent.getByte(address);
}
}public final class PlatformDependent {
public static byte getByte(long address) {
return PlatformDependent0.getByte(address);
}
}final class PlatformDependent0 {
static final Unsafe UNSAFE;
static byte getByte(long address) {
return UNSAFE.getByte(address);
}
}可以看到能获取到数据的核心是 memoryAddress,接下来看下 PoolArena#allocate() 方法,会对 memoryAddress 进行赋值
abstract class PoolArena<T> implements PoolArenaMetric {
PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) {
PooledByteBuf<T> buf = newByteBuf(maxCapacity);
// 在此处调用了 allocate,是在分配新的 ByteBuf 之后
allocate(cache, buf, reqCapacity);
return buf;
}
}abstract class PoolArena<T> implements PoolArenaMetric {
// 默认值是: -8192。 0x1111_1111_1111_1111_1110_0000_0000_0000
final int subpageOverflowMask;
private void allocate(PoolThreadCache cache, PooledByteBuf<T> buf, final int reqCapacity) {
// 计算实际的大小
final int normCapacity = normalizeCapacity(reqCapacity);
if (isTinyOrSmall(normCapacity)) {
// 容量小于页大小
int tableIdx;
PoolSubpage<T>[] table;
boolean tiny = isTiny(normCapacity);
if (tiny) { // < 512
// TODO:
if (cache.allocateTiny(this, buf, reqCapacity, normCapacity)) {
return;
}
tableIdx = tinyIdx(normCapacity);
table = tinySubpagePools;
} else {
// .........
}
final PoolSubpage<T> head = table[tableIdx];
synchronized (this) {
// 调用了 memory 的赋值
allocateNormal(buf, reqCapacity, normCapacity, cache);
}
incTinySmallAllocation(tiny);
return;
}
//.........
}
boolean isTinyOrSmall(int normCapacity) {
// 范围大概是 0 < ? < 8192。
return (normCapacity & subpageOverflowMask) == 0;
}
// ? < 512
static boolean isTiny(int normCapacity) {
return (normCapacity & 0xFFFFFE00) == 0;
}
}abstract class PoolArena<T> implements PoolArenaMetric {
private final PoolChunkList<T> qInit;
private void allocateNormal(PooledByteBuf<T> buf, int reqCapacity, int normCapacity, PoolThreadCache threadCache) {
//.......
// TODO:
PoolChunk<T> c = newChunk(pageSize, maxOrder, pageShifts, chunkSize);
boolean success = c.allocate(buf, reqCapacity, normCapacity, threadCache);
qInit.add(c);
}
}final class PoolChunk<T> implements PoolChunkMetric {
boolean allocate(PooledByteBuf<T> buf, int reqCapacity, int normCapacity, PoolThreadCache threadCache) {
final long handle;
if ((normCapacity & subpageOverflowMask) != 0) {
//.........
} else {
handle = allocateSubpage(normCapacity);
}
// nioBuffer = null
initBuf(buf, nioBuffer, handle, reqCapacity, threadCache);
return true;
}
}final class PoolChunk<T> implements PoolChunkMetric {
void initBuf(PooledByteBuf<T> buf, ByteBuffer nioBuffer, long handle, int reqCapacity,
PoolThreadCache threadCache) {
int memoryMapIdx = memoryMapIdx(handle);
int bitmapIdx = bitmapIdx(handle);
if (bitmapIdx == 0) {
// .......
} else {
initBufWithSubpage(buf, nioBuffer, handle, bitmapIdx, reqCapacity, threadCache);
}
}
}final class PoolChunk<T> implements PoolChunkMetric {
private void initBufWithSubpage(PooledByteBuf<T> buf, ByteBuffer nioBuffer,
long handle, int bitmapIdx, int reqCapacity, PoolThreadCache threadCache) {
int memoryMapIdx = memoryMapIdx(handle);
PoolSubpage<T> subpage = subpages[subpageIdx(memoryMapIdx)];
buf.init(
this, nioBuffer, handle,
runOffset(memoryMapIdx) + (bitmapIdx & 0x3FFFFFFF) * subpage.elemSize + offset,
reqCapacity, subpage.elemSize, threadCache);
}
}final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
private long memoryAddress;
@Override
void init(PoolChunk<ByteBuffer> chunk, ByteBuffer nioBuffer,
long handle, int offset, int length, int maxLength, PoolThreadCache cache) {
super.init(chunk, nioBuffer, handle, offset, length, maxLength, cache);
initMemoryAddress();
}
private void initMemoryAddress() {
// 最终在这里完成了对 memoryAddress 的赋值
memoryAddress = PlatformDependent.directBufferAddress(memory) + offset;
}
}先看赋值的方法
abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
protected T memory;
protected int offset;
private void init0(PoolChunk<T> chunk, ByteBuffer nioBuffer,
long handle, int offset, int length, int maxLength, PoolThreadCache cache) {
memory = chunk.memory;
this.offset = offset;
}
}final class PoolChunk<T> implements PoolChunkMetric {
final int offset;
private void initBufWithSubpage(PooledByteBuf<T> buf, ByteBuffer nioBuffer,
long handle, int bitmapIdx, int reqCapacity, PoolThreadCache threadCache) {
int memoryMapIdx = memoryMapIdx(handle);
PoolSubpage<T> subpage = subpages[subpageIdx(memoryMapIdx)];
buf.init(
this, nioBuffer, handle,
// 赋值位置,太复杂了,就不看了
runOffset(memoryMapIdx) + (bitmapIdx & 0x3FFFFFFF) * subpage.elemSize + offset,
reqCapacity, subpage.elemSize, threadCache);
}
}abstract class PoolArena<T> implements PoolArenaMetric {
final int chunkSize;
private void allocateNormal(PooledByteBuf<T> buf, int reqCapacity, int normCapacity, PoolThreadCache threadCache) {
//.........
// newChunk
PoolChunk<T> c = newChunk(pageSize, maxOrder, pageShifts, chunkSize);
boolean success = c.allocate(buf, reqCapacity, normCapacity, threadCache);
//.........
}
}abstract class PoolArena<T> implements PoolArenaMetric {
static final class DirectArena extends PoolArena<ByteBuffer> {
@Override
protected PoolChunk<ByteBuffer> newChunk(int pageSize, int maxOrder,
int pageShifts, int chunkSize) {
if (directMemoryCacheAlignment == 0) {
// chunk 的构造器在下面介绍
return new PoolChunk<ByteBuffer>(this,
// 重点看下 allocateDirect
allocateDirect(chunkSize), pageSize, maxOrder,
pageShifts, chunkSize, 0);
}
// .........
}
}
}abstract class PoolArena<T> implements PoolArenaMetric {
static final class DirectArena extends PoolArena<ByteBuffer> {
private static ByteBuffer allocateDirect(int capacity) {
return PlatformDependent.useDirectBufferNoCleaner() ?
PlatformDependent.allocateDirectNoCleaner(capacity)
// 由于条件是false,最终调用这里
: ByteBuffer.allocateDirect(capacity);
}
}
}可以看到,最终还是依赖了 jdk 的 DirectByteBuffer,大小是
public abstract class ByteBuffer
extends Buffer
implements Comparable<ByteBuffer> {
public static ByteBuffer allocateDirect(int capacity) {
return new DirectByteBuffer(capacity);
}
}final class PoolChunk<T> implements PoolChunkMetric {
final T memory;
PoolChunk(PoolArena<T> arena, T memory, int pageSize, int maxOrder, int pageShifts, int chunkSize, int offset) {
//.......
this.memory = memory;
}
}abstract class PoolArena<T> implements PoolArenaMetric {
final int chunkSize;
protected PoolArena(PooledByteBufAllocator parent, int pageSize,
int maxOrder, int pageShifts, int chunkSize, int cacheAlignment) {
this.chunkSize = chunkSize;
}
}abstract class PoolArena<T> implements PoolArenaMetric {
static final class DirectArena extends PoolArena<ByteBuffer> {
DirectArena(PooledByteBufAllocator parent, int pageSize, int maxOrder,
int pageShifts, int chunkSize, int directMemoryCacheAlignment) {
super(parent, pageSize, maxOrder, pageShifts, chunkSize,
directMemoryCacheAlignment);
}
}
}public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
private final PoolArena<ByteBuffer>[] directArenas;
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize, int normalCacheSize,
boolean useCacheForAllThreads, int directMemoryCacheAlignment) {
if (nDirectArena > 0) {
// 默认是 cpu 核数的 2倍大小
directArenas = newArenaArray(nDirectArena);
for (int i = 0; i < directArenas.length; i ++) {
PoolArena.DirectArena arena = new PoolArena.DirectArena(
this, pageSize, maxOrder, pageShifts, chunkSize, directMemoryCacheAlignment);
directArenas[i] = arena;
metrics.add(arena);
}
}
}
}public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize, int normalCacheSize,
boolean useCacheForAllThreads, int directMemoryCacheAlignment) {
chunkSize = validateAndCalculateChunkSize(pageSize, maxOrder);
}
}public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize, int normalCacheSize) {
this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder, tinyCacheSize, smallCacheSize,
normalCacheSize, DEFAULT_USE_CACHE_FOR_ALL_THREADS, DEFAULT_DIRECT_MEMORY_CACHE_ALIGNMENT);
}
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder) {
this(preferDirect, nHeapArena, nDirectArena, pageSize, maxOrder,
DEFAULT_TINY_CACHE_SIZE, DEFAULT_SMALL_CACHE_SIZE, DEFAULT_NORMAL_CACHE_SIZE);
}
public PooledByteBufAllocator(boolean preferDirect) {
this(preferDirect, DEFAULT_NUM_HEAP_ARENA, DEFAULT_NUM_DIRECT_ARENA, DEFAULT_PAGE_SIZE, DEFAULT_MAX_ORDER);
}
}DEFAULT_PAGE_SIZE 与 DEFAULT_MAX_ORDER, DEFAULT_NUM_DIRECT_ARENA
public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
static {
int defaultPageSize = SystemPropertyUtil.getInt("io.netty.allocator.pageSize", 8192);
validateAndCalculatePageShifts(defaultPageSize);
DEFAULT_PAGE_SIZE = defaultPageSize;
int defaultMaxOrder = SystemPropertyUtil.getInt("io.netty.allocator.maxOrder", 11);
validateAndCalculateChunkSize(DEFAULT_PAGE_SIZE, defaultMaxOrder);
DEFAULT_MAX_ORDER = defaultMaxOrder;
// cpu 核数的2倍
final int defaultMinNumArena = NettyRuntime.availableProcessors() * 2;
// 16mb
final int defaultChunkSize = DEFAULT_PAGE_SIZE << DEFAULT_MAX_ORDER;
// 如果 cpu 核数 小于 21,以 cpu 核数为准
DEFAULT_NUM_DIRECT_ARENA = Math.max(0,
SystemPropertyUtil.getInt(
"io.netty.allocator.numDirectArenas",
(int) Math.min(
defaultMinNumArena,
// 计算后的结果是 42
PlatformDependent.maxDirectMemory() / defaultChunkSize / 2 / 3)));
}
}计算 chunkSize 过程, validateAndCalculateChunkSize,根据默认值最终结果是 16777216 = 16384kb = 16Mb
public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
// INT最大值的一半
private static final int MAX_CHUNK_SIZE = (int) (((long) Integer.MAX_VALUE + 1) / 2);
private static int validateAndCalculateChunkSize(int pageSize, int maxOrder) {
if (maxOrder > 14) {
throw new IllegalArgumentException("maxOrder: " + maxOrder + " (expected: 0-14)");
}
int chunkSize = pageSize;
// 每一个 order 就会导致 chunkSize * 2
for (int i = maxOrder; i > 0; i --) {
if (chunkSize > MAX_CHUNK_SIZE / 2) {
throw new IllegalArgumentException(String.format(
"pageSize (%d) << maxOrder (%d) must not exceed %d", pageSize, maxOrder, MAX_CHUNK_SIZE));
}
chunkSize <<= 1;
}
return chunkSize;
}
}默认的 nDirectArena 是 cpu 核数的2倍,但 cpu 核数超过某个值和 maxDirectMemory 有关
public final class PlatformDependent {
private static final Pattern MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN = Pattern.compile(
"\\s*-XX:MaxDirectMemorySize\\s*=\\s*([0-9]+)\\s*([kKmMgG]?)\\s*$");
private static final long MAX_DIRECT_MEMORY = maxDirectMemory0();
private static final long DIRECT_MEMORY_LIMIT;
static {
long maxDirectMemory = SystemPropertyUtil.getLong("io.netty.maxDirectMemory", -1);
DIRECT_MEMORY_LIMIT = maxDirectMemory >= 1 ? maxDirectMemory : MAX_DIRECT_MEMORY;
}
private static long maxDirectMemory0() {
List<String> vmArgs = (List<String>) runtimeClass.getDeclaredMethod("getInputArguments").invoke(runtime);
for (int i = vmArgs.size() - 1; i >= 0; i --) {
// 如果设置了 -XX:MaxDirectMemorySize, 则读取该值
Matcher m = MAX_DIRECT_MEMORY_SIZE_ARG_PATTERN.matcher(vmArgs.get(i));
if (!m.matches()) {
continue;
}
maxDirectMemory = Long.parseLong(m.group(1));
switch (m.group(2).charAt(0)) {
case 'k': case 'K':
maxDirectMemory *= 1024;
break;
case 'm': case 'M':
maxDirectMemory *= 1024 * 1024;
break;
case 'g': case 'G':
maxDirectMemory *= 1024 * 1024 * 1024;
break;
}
break;
}
if (maxDirectMemory <= 0) {
// 直接读取系统最大内存
maxDirectMemory = Runtime.getRuntime().maxMemory();
}
}
}public class PooledByteBufAllocator extends AbstractByteBufAllocator implements ByteBufAllocatorMetricProvider {
final class PoolThreadLocalCache extends FastThreadLocal<PoolThreadCache> {
@Override
protected synchronized PoolThreadCache initialValue() {
// 调用链下面的方法
final PoolArena<ByteBuffer> directArena = leastUsedArena(directArenas);
// 选择出来的 directArena 会存储到 cache 中
final PoolThreadCache cache = new PoolThreadCache(
heapArena, directArena, tinyCacheSize, smallCacheSize, normalCacheSize,
DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL);
return cache;
}
private <T> PoolArena<T> leastUsedArena(PoolArena<T>[] arenas) {
PoolArena<T> minArena = arenas[0];
for (int i = 1; i < arenas.length; i++) {
PoolArena<T> arena = arenas[i];
//比较使用量,选择一个最少的
if (arena.numThreadCaches.get() < minArena.numThreadCaches.get()) {
minArena = arena;
}
}
return minArena;
}
}
// 对象池的线程局部变量
private final PoolThreadLocalCache threadCache;
public PooledByteBufAllocator(boolean preferDirect, int nHeapArena, int nDirectArena, int pageSize, int maxOrder,
int tinyCacheSize, int smallCacheSize, int normalCacheSize,
boolean useCacheForAllThreads, int directMemoryCacheAlignment) {
threadCache = new PoolThreadLocalCache(useCacheForAllThreads);
}
}final class PoolThreadCache {
final PoolArena<ByteBuffer> directArena;
private final MemoryRegionCache<ByteBuffer>[] normalDirectCaches;
PoolThreadCache(PoolArena<byte[]> heapArena, PoolArena<ByteBuffer> directArena,
int tinyCacheSize, int smallCacheSize, int normalCacheSize,
int maxCachedBufferCapacity, int freeSweepAllocationThreshold) {
this.directArena = directArena;
if (directArena != null) {
normalDirectCaches = createNormalCaches(
normalCacheSize, maxCachedBufferCapacity, directArena);
directArena.numThreadCaches.getAndIncrement();
}
}
}- 直接内存 ByteBuf 对象池存储在了线程局部变量中,线程结束的时候销毁