Categories
Coding

Buggy MemoryMapping in the JDK

I just ran into a problem using memory-mapped byte buffers on Java 5. The basic use case is read from a socket, write to a file, and then map the resulting file into memory to perform digest calculations, etc. across the entire file. It works the first time, but any subsequent attempt to rewrite the file will fail with the message The requested operation cannot be performed on a file with a user-mapped section open.

After some searching, I found that this is a relatively common problem, and it is a facet of the way that memory mapping actually works on the underlying OS. It seems you can have speed, or safety, but not both. The issue is with the current impossibility of producing a reliable and platform-independent unmap command. An example of unmap() at the C level can be seen here.

In fairness to Sun, it’s probably not fair to blame them for the existance of this problem – it seems to be currently intractable. The end of their evaluation note in the Bug Parade entry for this bug reads:

We at Sun have given this problem a lot of thought, both during the original
development of NIO and in the time since. We have yet to come up with a way to
implement an unmap() method that’s safe, efficient, and plausibly portable
across operating systems. We’ve explored several other alternatives aside from
the two described above, but all of them were even more problematic. We’d be
thrilled if someone could come up with a workable solution, so we’ll leave this
bug open in the hope that it will attract attention from someone more clever
than we are.

Just for reference, the code that creates the buffer is shown below:


 FileChannel fc = new FileInputStream(requestedFile).getChannel();
       int sz = (int)fc.size();
       
       MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
       
       byte buffer[] new byte[sz];
       bb.get(buffer, 0, sz);

Leave a Reply