Java DirectByteBuffer 包装器是否被垃圾收集?
我知道分配directbytebuffer时,它不受垃圾回收的影响,但我想知道包装对象是否被垃圾回收.
I understand that when a directbytebuffer is allocated, its not subject to garbage collection, but what I'm wondering is if the wrapping object is garbage collected.
例如,如果我分配了一个新的 DirectByteBuffer dbb,然后使用 dbb.duplicate() 复制(浅复制)它,我将在同一块内存周围有两个包装器.
For example, if I allocated a new DirectByteBuffer dbb, and then duplicated(shallow copied) it using dbb.duplicate(), I'd have two wrappers around the same chunk of memory.
这些包装器会受到垃圾回收吗?如果我这样做了
Are those wrappers subject to garbage collection? If I did
while(true){
DirectByteBuffer dbb2 = dbb.duplicate();
}
我最终会自己 OOM 吗?
Would I eventually OOM myself?
推荐答案
在 Sun JDK 中,一个 java.nio.DirectByteBuffer
—由 ByteBuffer#allocateDirect(int)
—有一个字段键入 sun.misc.Cleaner
,它扩展了 java.lang.ref.PhantomReference
.
In the Sun JDK, a java.nio.DirectByteBuffer
—created by ByteBuffer#allocateDirect(int)
—has a field of type sun.misc.Cleaner
, which extends java.lang.ref.PhantomReference
.
当这个 Cleaner
(记住,PhantomReference
的子类型)被收集并即将移动到关联的 ReferenceQueue
时,收集-通过嵌套类型 ReferenceHandler
运行的相关线程对 Cleaner
实例进行了特殊处理:它向下转换并调用 Cleaner#clean()
,它最终返回调用 DirectByteBuffer$Deallocator#run()
,而后者又调用 Unsafe#freeMemory(long)
.哇.
When this Cleaner
(remember, a subtype of PhantomReference
) gets collected and is about to move into the associated ReferenceQueue
, the collection-related thread running through the nested type ReferenceHandler
has a special case treatment of Cleaner
instances: it downcasts and calls on Cleaner#clean()
, which eventually makes its way back to calling on DirectByteBuffer$Deallocator#run()
, which in turn calls on Unsafe#freeMemory(long)
. Wow.
这是相当迂回的,我很惊讶没有看到 Object#finalize()
的任何使用.Sun 开发人员一定有他们的理由将其与收集和引用管理子系统联系得更紧密.
It's rather circuitous, and I was surprised to not see any use of Object#finalize()
in play. The Sun developers must have had their reasons for tying this in even closer to the collection and reference management subsystem.
简而言之,你不会因为放弃对 DirectByteBuffer
实例的引用而耗尽内存,只要垃圾收集器有机会注意到放弃并且它的引用处理线程取得进展通过上述调用.
In short, you won't run out of memory by virtue of abandoning references to DirectByteBuffer
instances, so long as the garbage collector has a chance to notice the abandonment and its reference handling thread makes progress through the calls described above.
相关文章