主要是通过AbstractByteBufAllocator类实现的ByteBuffer的申请。
代码如下:
@Override public ByteBuf ioBuffer(int initialCapacity) { if (PlatformDependent.hasUnsafe()) { return directBuffer(initialCapacity); } return heapBuffer(initialCapacity); } @Override public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) { if (PlatformDependent.hasUnsafe()) { return directBuffer(initialCapacity, maxCapacity); } return heapBuffer(initialCapacity, maxCapacity); }
会根据是否有Unsafe的类支持来判断是否需要使用“堆外内存”;如果配置了3种情况则不会使用
(1)io.netty.noUnsafe这个属性false
(2)io.netty.tryUnsafe这个属性false
(3)org.jboss.netty.tryUnsafe这个属性false
我们暂且排除这3个配置,它会默认去尝试创建Unsafe类并且尝试ByteBuffer direct = ByteBuffer.allocateDirect(1);如果成功了就是用堆外内存的方式创建数据缓冲区。
内存缓冲区的创建是由netty本身去推测执行的。
核心类为:AdaptiveRecvByteBufAllocator
该类的初始化时使用一段静态代码块来包装ByteBuffer的申请内存大小的可能,代码如下:
static { List<Integer> sizeTable = new ArrayList<Integer>(); for (int i = 16; i < 512; i += 16) { sizeTable.add(i);//从16字节大小开始,每次增加16不超512 } for (int i = 512; i > 0; i <<= 1) { sizeTable.add(i);//512以后每次扩容大小乘以2,直到溢出为止 } SIZE_TABLE = new int[sizeTable.size()]; for (int i = 0; i < SIZE_TABLE.length; i ++) { SIZE_TABLE[i] = sizeTable.get(i); } }
创建的缓冲区从大小从16开始,最大到int溢出。
而且默认的开始分配为1024个字节,不小于64字节,不大于65536字节。
static final int DEFAULT_MINIMUM = 64; static final int DEFAULT_INITIAL = 1024; static final int DEFAULT_MAXIMUM = 65536;