DirectByteBuffer in Java
MappedByteBuffer is a way to read and write binary files directly in Java. It allows you to address file data at the bytes level, so it is convenient and potentially high performance.
It maps a file region into the virtual address space of the Java process. Here's a simple example of how to use it (also on GitHub):
On further thought, there seems to be a problem with this class. There's no public API to unmap the file out of the process address space. This will cause issues on Windows, which locks the file and the mapped region. While examining the instance of the class under the IntelliJ debugger, I noticed the private field called cleaner.
It maps a file region into the virtual address space of the Java process. Here's a simple example of how to use it (also on GitHub):
public class MappedByteBufferTest {
public static void main(String[] args) throws IOException {
//WRITE FILE
int len = 200;
RandomAccessFile file = new RandomAccessFile("output.txt", "rw");
MappedByteBuffer outputBuffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, len);
for (int i = 0; i < len; i++)
outputBuffer.put((byte) i);
//READ FILE
FileInputStream inputStream = new FileInputStream("output.txt");
MappedByteBuffer mappedByteBuffer = inputStream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, len);
for (int i = 0; i < len; i++) {
if(mappedByteBuffer.get(i) != (byte) i)
throw new IOException("oops");
}
((sun.nio.ch.DirectBuffer) mappedByteBuffer).cleaner().clean();
}
}
On further thought, there seems to be a problem with this class. There's no public API to unmap the file out of the process address space. This will cause issues on Windows, which locks the file and the mapped region. While examining the instance of the class under the IntelliJ debugger, I noticed the private field called cleaner.
This piqued my interest on how to use the cleaner. By studying the source code of the openJDK, I learned that MappedByteBuffer is a subclass of sun.nio.ch.DirectBuffer. Each unmapped region is associated with a thread. Though it seems like an overkill, this allows to automatically unmap the region (though nondeterministically). The following code snippet will force the cleaner thread to run:
((sun.nio.ch.DirectBuffer) mappedByteBuffer).cleaner().clean();
Out of curiosity, I did some Googling to see if there is an issue with this nondeterministic behavior. I found an interesting example. Kafka is a distributed program for sending and receiving messages. It seems to be a pretty simple case. I created a pull request with my limited knowledge of Scala.