0

I am learning java nio and I am using MappedByteBuffer and ExecutorService to copy files asynchronously. My problem is the method MappedByteBuffer.put() is throwing java.nio.BufferOverflowException. But in my debug I am not copying to over position on my target file. This is the part of the code that I use to create the new copy of the file:

for (Future<?> f : futures) {
                Message message = (Message) f.get();
                try (FileChannel fileChannel = (FileChannel) Files
                        .newByteChannel(pathWrite, EnumSet.of(
                                StandardOpenOption.READ,
                                StandardOpenOption.WRITE,
                                StandardOpenOption.TRUNCATE_EXISTING))) {
                    MappedByteBuffer mbb = fileChannel.map(
                            FileChannel.MapMode.READ_WRITE, message.getCod(),
                            message.getValue());

                    if (mbb != null) {
                        System.out.println("start: " + message.getCod()
                                + " - end: " + message.getValue());
                        ByteBuffer encode = Charset.forName(charEncoding)
                                .encode(message.getCharBuffer());
                        mbb.put(encode); // here
                    }
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

and the exception is :

java.nio.BufferOverflowException
    at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:363)
    at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:342)
    at memo.MultiThreadingMappedByteBufferExample.multiThreadedWayWithExecutorService(MultiThreadingMappedByteBufferExample.java:139)
Felipe
  • 7,013
  • 8
  • 44
  • 102

1 Answers1

2

You're truncating the file to zero length, mapping some unknown part of it according to the offset and length values provided by message.getCod() and message.getValue(), which doesn't exist because the file is zero length, and then trying to put the charBuffer provided with the message into the file, which is still zero length, at the offset defined by message.getCod(), which doesn't exist, so you get a BufferOverflowException.

I suggest you don't truncate the file to start with, but it isn't clear why any of this should work. I suggest you use a RandomAccessFile. Simpler. You shouldn't use lots of memory-mapped files in a single application, and using it just for this tiny job is inappropriate.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • As I am learning java nio I want to use its ways to improve the performance of a big program that use concurrency and asynchrony jobs. This is just a first try to help me to the big try. If you have some example with MappedByteBuffer it will help me very much. Thanks anyway. – Felipe Feb 10 '15 at 00:56
  • 1
    It won't improve the performance. It will make it worse. The [Javadoc](https://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html#map(java.nio.channels.FileChannel.MapMode,%20long,%20long)) says so: "For most operating systems, mapping a file into memory is more expensive than reading or writing a few tens of kilobytes of data via the usual read and write methods. From the standpoint of performance it is generally only worth mapping relatively large files into memory." If you are just learning Java you should certainly do things the easy way at first. – user207421 Feb 10 '15 at 01:00