先看注释
/**
* A pool of ByteBuffers kept under a given memory limit. This class is fairly specific to the needs of the producer. In
* particular it has the following properties:
* <ol>
* <li>There is a special "poolable size" and buffers of this size are kept in a free list and recycled
* <li>It is fair. That is all memory is given to the longest waiting thread until it has sufficient memory. This
* prevents starvation or deadlock when a thread asks for a large chunk of memory and needs to block until multiple
* buffers are deallocated.
* </ol>
*/
结合代码可知,BufferPool负责ByteBuffer的申请和释放。
BufferPool会维持一组大小为poolableSize的ByteBuffer,便于快速申请/归还这个大小的ByteBuffer。该机制是由free
空闲链表维持的。
对于非poolableSize的ByteBuffer,其申请和释放都委托给JVM
BufferPool的内存申请是"公平的",永远优先满足先申请的线程,再满足后申请的。这样能防止死锁和饥饿。该机制是由waiters
条件队列保障的。
BufferPool将内存视为三个部分:
free
空闲链表的ByteBuffer(free
会维持它们的引用)。每一个的大小都是poolableSize。 free
中取出即可free
ByteBuffer.allocate(size)
维持了一个Condition队列,每个线程在申请内存不足时,会阻塞于生成的一个Condition并进入此队。
private final Deque<Condition> waiters;
比如此处,在allocate方法中,没有足够内存:
所以,队列中每一个Condition代表一个因内存不足而阻塞的线程,当有ByteBuffer释放时,取出队首的Condition,调用signal
将对应线程唤醒即可。
根据要分配的内存大小有不同的行为。
如果要分配的内存size等于poolableSize,从free
取出一块即可。如果free
没有就等待。
如果size不等于poolableSize,需要从非池化内存分配:
free
中的ByteBuffer,直到有足够的nonPooledAvailableMemory为止free
,也可能有新的非池化内存,使nonPooledAvailableMemory增加),若超时就抛出内存不足异常,否则返回时未超时,说明有新的空闲内存了。free
中的ByteBuffer,直到有足够nonPooledAvailableMemory为止。期间会扣除nonPooledAvailableMemory的份额,加到accumulated上。但我们并不申请内存,只是把这块份额预留出来。对归还的份额有疑问:
归还size?
根据要释放的内存大小有不同的行为。
size
即可对代码关于非池化内存的回收行为有疑问: