1:PooledByteBufAllocator 内存池入口,应用通过该类从内存池中申请内存
PoolThreadCache:线程缓存池
Recycler:上文的Recycler是个对象池,储存的是相应类型的堆中对象的集合。
2:PooledByteBufAllocator获取bytebuf步骤:
1)如果是pool类型,先在线程对象池中获取一个相应类型的poolBuffer对象,这个对象是在堆中的,也是返回的对象,然后会使用PoolThreadCache这个线程内存池,获取一块合适大小的内存。接下来根据这块内存的信息对这个poolBuffer对象进行init,比如设置内存的address,length等,用户就可以通过这个buffer对象对相应的内存进行操作。
2)注意区别线程对象池和线程内存池。线程对象池指同一类型的对象集合,用户也只能通过对象来进行操作,比如读写数据。而线程内存池是许多内存块的集合,用户通过对象读写数据还是要定位到实际的内存地址(虚拟内存地址)。内存池就通过把对象和一块内存绑定,对象的读写操作都会反应到这块内存上。
3)内存是有限的,为了最大化内存的利用率以及提高内存分配回收的效率,netty实现了类似jemalloc内存分配的方式给对象分配内存。
4)获取一个buffer对象-->给buffer对象属性赋值(赋的值就是内存的地址、大小)
5) 比如现在需要分配一个UnpooledHeapByteBuf类型的ByteBuf对象,其初始大小为20,最大容量为100,因为是unpooled,意味着这各类型的ByteBuf是没有对象池的,需要的时候直接new一个即可
(1)new UnpooledHeapByteBuf(this,initialCapacity,maxCapacity);
单纯的一个没有经过初始化(成员变量没有赋值)的ByteBuf是不能进行读写的,因为其读写方法都需要确切的读写内存地址的。对于UnpooledHeapByteBuf类型的ByteBuf,其是一个HeapByteBuf,Heap意味着这个ByteBuf的读写操作是在JVM堆上进行的,其读写内存地址需要在jvm对上进行分配,所以在初始化时要根据需要的大小创建一个Byte类型的数组Byte[]对UnpooledDirectByteBuf进行初始化,接下来对这个Buf的读写都会反应在这个字节数组中。
6)对于UnpooledDirectByteBuf类型的ByteBuf,Direct意味着这个ByteBuf的读写实现方法是以直接内存为基础进行实现的,其读写区域是在直接内存上,在初始化时构造一个DirectByteBuffer对象(nio中的ByteBuffer)赋值给UnpooledDirectByteBuf的buf属性,接下来对这个UnpooledDirectByteBuf类型对象的读写都会反应到这个ByteBuffer上。
7)对于pool类型的,