How to Unmap a File from Memory Mapped Using Filechannel in Java

How to unmap a file from memory mapped using FileChannel in java?

From the MappedByteBuffer javadoc:

A mapped byte buffer and the file mapping that it represents remain valid until the buffer itself is garbage-collected.

Try calling System.gc()? Even that's only a suggestion to the VM.

Truncate memory mapped file

Your issue is that you are using unreliable method to close mapped byte buffer (one hundred calls to System.gc() and System.runFinalization() don't guarantee you anything). Unfortunately there is no reliable method in Java API to do that, but on Sun JVM (and perhaps on some others too) you can use the following code:

public void unmapMmaped(ByteBuffer buffer) {
if (buffer instanceof sun.nio.ch.DirectBuffer) {
sun.misc.Cleaner cleaner = ((sun.nio.ch.DirectBuffer) buffer).cleaner();
cleaner.clean();
}
}

Of course it is JVM-dependent and you should be ready to fix your code if Sun ever decides to change sun.nio.ch.DirectBuffer or sun.misc.Cleaner in an incompatible manner (but actually I don't believe this will ever happen).

Windows: moving a file that was previously mapped in memory fails

In Java, file mappings are garbage collected, and there is no supported way to forcibly destroy a mapping.

From the FileChannel.map() documentation:

The buffer and the mapping that it represents will remain valid until
the buffer itself is garbage-collected.

A mapping, once established, is not dependent upon the file channel
that was used to create it. Closing the channel, in particular, has
no effect upon the validity of the mapping.

In Sun's JDK, you can test that this is indeed the culprit by forcibly destroying the mapping just before doing the file move:

import sun.nio.ch.DirectBuffer;
import sun.misc.Cleaner;
[...]
if (byteBuffer.isDirect()) {
Cleaner cleaner = ((DirectBuffer) byteBuffer).cleaner();
cleaner.clean();
}
// move file


Related Topics



Leave a reply



Submit