我知道当分配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
实例的引用而耗尽内存。