AsynchronousFileChannel write failure

662 views Asked by At

I am trying to write an image to a file using AsynchronousFileChannel.write:

    ...
    Path filePath = Paths.get(path + "/" + System.currentTimeMillis()
            + ".jpeg");
    try (AsynchronousFileChannel channel = AsynchronousFileChannel.open(filePath,
            StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);) {
        CompletionHandler<Integer, Object> handler = new CompletionHandler<Integer, Object>() {

            @Override
            public void failed(Throwable exc, Object attachment) {
                logger.error("Write failed: ", exc);
            }

            @Override
            public void completed(Integer result, Object attachment) {
                ...
            }
        };

        ByteBuf buffer = Unpooled.buffer(request.getImage().length);
        buffer.writeBytes(request.getImage());
        channel.write(buffer.nioBuffer(), 0, null, handler);
    } catch (IOException e) {
        logger.error("Failed to open file: ", e);
        throw new RuntimeException(e);
    }

....

I very often receive the following exception:

java.nio.channels.AsynchronousCloseException: null
    at sun.nio.ch.SimpleAsynchronousFileChannelImpl$3.run(SimpleAsynchronousFileChannelImpl.java:380) ~[na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]

I run this code on Linux using Oracle JDK 8u25. This is exception occoured a lot less on Windows. And I also noticed when I run the code in debug mode, stepping over each line of code, it rarely happens.

When I do not use the CompletionHandler, but rather use:

    Future<Integer> writeFuture = channel.write(buffer.nioBuffer(), 0);
    Integer integer = writeFuture.get();

I don't get the exception.

What could be causing this?

1

There are 1 answers

0
Norman Maurer On BEST ANSWER

I think it is because you auto close the Channel when you leave the try {...} block and the write you are doing is async, which means that if your write is not done fast-enough you will try to write to a closed channel.