Are Java DirectByteBuffer wrappers garbage collect

2019-01-22 09:23发布

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.

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();
} 

Would I eventually OOM myself?

4条回答
戒情不戒烟
2楼-- · 2019-01-22 10:06

A direct ByteBuffer object is just like any other object: it can be garbage-collected.

The memory used by a direct buffer will be released when the ByteBuffer object is GC'd (this is not explicitly stated for ByteBuffer, but is implied by the documentation of MappedByteBuffer).

Where things get interesting is when you've filled your virtual memory space with direct buffers, but still have lots of room in the heap. It turns out that (at least on the Sun JVM), running out of virtual space when allocating a direct buffer will trigger a GC of the Java heap. Which may collect unreferenced direct buffers and free their virtual memory commitment.

If you're running on a 64-bit machine, you should use -XX:MaxDirectMemorySize, which puts an upper limit on the number of buffers that you can allocate (and also triggers GC when you hit that limit).

查看更多
我命由我不由天
3楼-- · 2019-01-22 10:16

Looking at the source code to DirectByteBuffer it just returns a new instance, so no, you won't OOM yourself.

As long as the rest of your code doesn't hold onto a reference to the original dbb then that object will get garbage collected as normal. The extra dbb2 objects will similarly get garbage collected when there is no longer any reference to them(ie, the end of the while loop).

查看更多
走好不送
4楼-- · 2019-01-22 10:17

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.

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.

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.

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.

查看更多
何必那么认真
5楼-- · 2019-01-22 10:19

when a directbytebuffer is allocated, its not subject to garbage collection

Where did you get that idea? It's not correct. Are you getting them mixed up with MappedByteBuffers?

查看更多
登录 后发表回答