Mar
2014
Method 2 of N for crashing your JVM :-)
On a previous post there was a short discussion about what’s the best way to clean up memory mapped files and Philippe brought to my attention the following text from a bugreport:
With regard to the “workaround”, described in the JDC comments, of (ab)using reflection in order to invoke a mapped buffer’s cleaner object: This is highly inadvisable, to put it mildly. It is exceedingly dangerous to forcibly unmap a
mapped byte buffer that’s visible to Java code. Doing so risks both the security and stability of the system.
So what is the problem with doing ((sun.nio.ch.DirectBuffer) buffer).cleaner().clean();
?
As explained briefly in the bug post, there are two potential issues:
- The first potential issue is that you might try to read/write from/to the buffer after calling the cleaner (because you have a bug in the code). This will bring down the JVM with SIGSEGV on Linux / EXCEPTION_ACCESS_VIOLATION under Windows
- The second potential issue is that somebody might remap an other file in the same address range after you’ve unmapped your file and you start to read (or even worse – write) to a different file.
Both of these issues are solved if you let the GC clean up the mappings (since when it runs you’re guaranteed that there are no other references to the object), but it might never collect your buffers.
An other possibility is to wrap the code up in a library which “does the right thing” (like Chronicle).
Finally, you could (and should) carefully design your program to avoid repeated (re-)allocation (ideally you should do all the allocations at startup and leave things alone afterwards). Besides removing the potential for the above issues, allocating direct memory buffers is a costly endeavor with the JVM: it is globally synchronized and it may trigger a GC and/or sleep (see FileChannelImpl.java and Bits.java).