DirectByteBuffer 里的堆外内存何时释放?
简要答案
DirectByteBuffer 在分配堆外内存时:
- 先要通过 Bits.reserveMemory 来看看是否还有可用的内存,是否达到了堆外内存的上限?有的话,占坑。
- 通过 unsafe.allocateMemory 分配内存。
- 创建 Cleaner,这个 Cleaner 就是用来管理堆外内存的。Cleaner 继承了 PhantomReference,当 GC 时发现它除了 PhantomReference 外已不可达(持有它的 DirectByteBuffer 失效了),就会把它放进 Reference 类 pending list 静态变量里。然后另有一条 ReferenceHandler 线程,名字叫”Reference Handler”的,关注着这个 pending list,如果看到有对象类型是 Cleaner,就会执行它的clean()。
DirectByteBuffer(int cap) { // package-private
super(-1, 0, cap, cap);
boolean pa = VM.isDirectMemoryPageAligned();
int ps = Bits.pageSize();
long size = Math.max(1L, (long)cap + (pa ? ps : 0));
Bits.reserveMemory(size, cap);