我知道当分配DirectbyteBuffer时,它不受垃圾回收的限制,但是我想知道的是包装对象是否被垃圾回收了。

例如,如果我分配了一个新的DirectByteBuffer dbb,然后使用dbb.duplicate()复制(浅复制)了它,那么我将在同一块内存中使用两个包装器。

这些包装器是否要进行垃圾收集?如果我做了

while(true){
    DirectByteBuffer dbb2 = dbb.duplicate();
}

我最终会自己OOM吗?

最佳答案

在Sun JDK中,由 java.nio.DirectByteBuffer 创建的ByteBuffer#allocateDirect(int)具有类型为sun.misc.Cleaner的字段,该字段扩展了 java.lang.ref.PhantomReference

当此Cleaner(记住,是PhantomReference的子类型)被收集并即将移入关联的ReferenceQueue时,通过嵌套类型ReferenceHandler运行的与集合相关的线程对Cleaner实例进行了特殊处理:它向下转换并调用Cleaner#clean(),最终又回到了调用DirectByteBuffer$Deallocator#run()的位置,后者又调用了Unsafe#freeMemory(long)。哇。

这相当circuit回,我很惊讶没有在游戏中使用Object#finalize()。 Sun开发人员必须将其原因归结到更靠近收集和引用管理子系统的地方。

简而言之,只要垃圾收集器有机会注意到这种废弃,并且其引用处理线程通过上述调用取得了进展,就不会因为放弃对DirectByteBuffer实例的引用而耗尽内存。

08-06 15:26