Reputation: 2489
I am planning to use a DirectByteBuffers to interface a third party lib written in C++.
I got worried from the hadoop docs saying:
DirectByteBuffers are garbage collected by using a phantom reference and a reference queue. Every once a while, the JVM checks the reference queue and cleans the DirectByteBuffers. However, as this doesn't happen immediately after discarding all references to a DirectByteBuffer, it's easy to OutOfMemoryError yourself using DirectByteBuffers.
First I am not sure if all implementations of DirectByteBuffers are the same since the OpenJDK 7 does not seem to use phantom reference, but relies on the finalize method which should have performance penalties.
Second, I tried to replicate an OutOfMemoryError using
public static void main(String[] args) {
for(;;){
ByteBuffer buff = ByteBuffer.allocateDirect(1000*1000);
}
}
and it seems that everything gets properly garbage collected. If this is the case on my machine using
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)
can I rely on that this will work on every other machine and java version >= 1.6?
Thanks
Upvotes: 0
Views: 259
Reputation: 53694
This is a great article on the subject.
As for your test, simple tests like that don't really exercise the problem area. the potential issue arises when the GC gets too far behind. in a test like that, the GC isn't doing anything else so likely won't have problem keeping up.
Upvotes: 2
Reputation: 533660
This was a bug in early versions of Java 6. However, a simple workaround which was included in the JVM was to throw an OutOfMemoryError only after triggering a System.gc(); Now you can simulate this problem by disabling explicit GCs.
Source for java.nio.Bits.reserveMemory(long)
I don't wait for the GC to clean up direct memory or memory mapped files, instead I use an internal API which is fine for OpenJDK based JVMs, e.g. Hotspot. This improves performance by reducing spurious Full GCs.
((DirectBuffer) buffer).cleaner().clean();
If you have heap buffers, cleaner() will return null.
Upvotes: 2