内存管理-PooledByteBufAllocator-Huge
PooledByteBufAllocator 即池化的 ByteBuf 分配器,整体算法实现都是比较复杂的,因此我们采用各个击破的方式进行介绍。
目标
1. Huge 堆上内存分配 & 释放
2. Huge 直接内存分配 & 释放
3. 了解 ByteBuf 是怎样持有堆上内存不让 JVM 回收的
示例
1 public class ByteBufTest { 2 3 public static void main(String[] args) { 4 ByteBufAllocator allocator = PooledByteBufAllocator.DEFAULT; 5 int hugeSize = 17 * 1024 * 1024; 6 ByteBuf hugeHeapBuf = allocator.heapBuffer(hugeSize); 7 hugeHeapBuf.release(); 8 ByteBuf hugeDirectBuf = allocator.directBuffer(hugeSize); 9 hugeDirectBuf.release(); 10 } 11 }
HeapByteBuf
申请
1 // PoolArena.java 2 3 PooledByteBuf<T> allocate(PoolThreadCache cache, int reqCapacity, int maxCapacity) { 4 // 创建一个 PooledByteBuf 的壳 5 PooledByteBuf<T> buf = newByteBuf(maxCapacity); 6 // 申请空间 7 allocate(cache, buf, reqCapacity); 8 return buf; 9 } 10 11 ... 12 13 private void allocateHuge(PooledByteBuf<T> buf, int reqCapacity) { 14 // huge 的 chunk 是 Unpooled 类型的 15 PoolChunk<T> chunk = newUnpooledChunk(reqCapacity); 16 activeBytesHuge.add(chunk.chunkSize()); 17 // 将这一部分空间交给 buf 来持有 18 buf.initUnpooled(chunk, reqCapacity); 19 allocationsHuge.increment(); 20 } 21 22 ... 23 24 protected PoolChunk<byte[]> newUnpooledChunk(int capacity) { 25 // newByteArray 在堆上申请空间,PoolChunk 中持有一个 memory 指向这片空间 26 return new PoolChunk<byte[]>(this, newByteArray(capacity), capacity, 0); 27 }
释放
1 // PooledByteBuf.java 2 3 protected final void deallocate() { 4 if (handle >= 0) { 5 final long handle = this.handle; 6 this.handle = -1; 7 // 将 memory 置为 null,去掉 ByteBuf 对这一块内存的使用 8 memory = null; 9 tmpNioBuf = null; 10 chunk.arena.free(chunk, handle, maxLength, cache); 11 chunk = null; 12 recycle(); 13 } 14 } 15 16 // PooledArena.java 17 void free(PoolChunk<T> chunk, long handle, int normCapacity, PoolThreadCache cache) { 18 if (chunk.unpooled) { 19 // 更新 chunk 的一些统计信息,归还内存到 chunk,由于是堆上的,因此 destroyChunk 什么都没做,交给 GC 来回收 20 int size = chunk.chunkSize(); 21 destroyChunk(chunk); 22 activeBytesHuge.add(-size); 23 deallocationsHuge.increment(); 24 } ...
DirectByteBuf
与 HeapByteBuf 类似,区别在于申请和释放直接内存的地方
申请
private static ByteBuffer allocateDirect(int capacity) {
return PlatformDependent.useDirectBufferNoCleaner() ?
PlatformDependent.allocateDirectNoCleaner(capacity) : ByteBuffer.allocateDirect(capacity);
}
释放
1 // PoolArena.java 2 protected void destroyChunk(PoolChunk<ByteBuffer> chunk) { 3 if (PlatformDependent.useDirectBufferNoCleaner()) { 4 // 将 chunk 指向的内存归还给直接内存 5 PlatformDependent.freeDirectNoCleaner(chunk.memory); 6 } else { 7 PlatformDependent.freeDirectBuffer(chunk.memory); 8 } 9 } 10 11 // PlatformDepent.java 12 public static void freeDirectNoCleaner(ByteBuffer buffer) { 13 assert USE_DIRECT_BUFFER_NO_CLEANER; 14 15 int capacity = buffer.capacity(); 16 // 采用 unsafe 的方式归还内存 PlatformDependent0.freeMemory(PlatformDependent0.directBufferAddress(buffer)); 17 decrementMemoryCounter(capacity); 18 }

浙公网安备 33010602011771号