Search code examples
javaniomemory-mapped-filesfilechannelrandom-access

In-memory version of Java's FileChannel


I'm in the process of making some changes to a library that I'm using. In order to reduce memory usage the library is writing its temporary data to disk instead of keeping it in memory. However, for my usage scenario it is more efficient to keep it in memory. It also has some concurrency issues, because it has constant names for its temp-files and can therefore not run concurrently in different threads (because the threads will corrupt each other's data).

I therefore need to change the library so that it keeps all its data in memory instead. I have not originally written the library and I'm therefore not very comfortable with making drastic changes to the code. I'd therefore like to do this with as little refactoring as possible. The code which writes to disk is quite simple. Here's a (somewhat simplified) example:

final FileChannel fileChannel = this.randomAccessFile.getChannel();
fileChannel.position(calculatePosition());
while (blockData.hasRemaining())
{
 fileChannel.write(blockData);
}

The reading of a block is very similar (i.e. it uses a FileChannel, which it gets from a RandomAccessFile).

It feels like the easiest solution would be if I can use some implementation of FileChannel, which maps to a place in memory instead of to a file. I know I can map a file to a place in memory using FileChannel's map-method. However, that is the other way around. That gives me a "memory-API" to a file. I want a FileChannel-interface against some memory. Are there any available implementations of this?


Solution

  • Java 7 will allow pluggable filesystems, so you'll be able to use a memory based filesystem and keep the current FileChannel API. Short of that you're likely to have to change the API you use to Commons-VFS as Adrian suggests or use memory only structures.

    EDIT per the 2023 update to this question, asking if this can be done without external libraries... I suspect this is the wrong question, because FileChannel will always specifically be connected to a file object.

    FileChannel consists mostly of a set of implemented interfaces...

    In particular, you probably are interested in the functionality of ByteChannel or ReadableByteChannel or SeekableByteChannel, all of which have fairly small footprints. It would be pretty easy to create a ByteBufferChannel that implements one of those.

    Just write your code expecting a FileChannel to instead use the actual java Interface you care about, and you can pass either a FileChannel or the proposed ByteBufferChannel in interchangably.