Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8274548

(fc) FileChannel gathering write fails with IOException "Invalid argument" on macOS 11.6

    XMLWordPrintable

Details

    • b19
    • aarch64
    • os_x
    • Verified

    Description

      ADDITIONAL SYSTEM INFORMATION :
      OSX 11.6 on Apple M1 MacBook Pro
      Fails on both the Arm64 and x86 version of JDK 17
      openjdk version "17" 2021-09-14
      OpenJDK Runtime Environment (build 17+35-2724)
      OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)


      A DESCRIPTION OF THE PROBLEM :
      FileChannel.write(ByteBuffer[] ..) with 3x 1Gb direct ByteBuffers fails with IOException
      Exception in thread "main" java.io.IOException: Invalid argument
              at java.base/sun.nio.ch.FileDispatcherImpl.writev0(Native Method)
              at java.base/sun.nio.ch.FileDispatcherImpl.writev(FileDispatcherImpl.java:74)
              at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:182)
              at java.base/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:314)
              at java.base/java.nio.channels.FileChannel.write(FileChannel.java:424)
              at jasperdb.FileChannel2GLimitTest.main(FileChannel2GLimitTest.java:23)
      It fails on Mac but works on linux with the but only writes 2Gb of data filled in bug internal review ID : 9071589

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Example failing code attached. Basically just call FIleChannel.write(new ByteBuffer[] {
                      ByteBuffer.allocateDirect(GB),
                      ByteBuffer.allocateDirect(GB),
                      ByteBuffer.allocateDirect(GB)
              })

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      File with 3GB of zero data
      ACTUAL -
      IOException

      ---------- BEGIN SOURCE ----------
      import java.io.IOException;
      import java.nio.ByteBuffer;
      import java.nio.channels.FileChannel;
      import java.nio.file.Files;
      import java.nio.file.Path;
      import java.nio.file.StandardOpenOption;

      public class FileChannel2GLimitTest {
          static final int GB = 1024*1024*1024;
          public static void main(String[] args) throws IOException {
              ByteBuffer[] bigBuffers = new ByteBuffer[] {
                      ByteBuffer.allocateDirect(GB),
                      ByteBuffer.allocateDirect(GB),
                      ByteBuffer.allocateDirect(GB)
              };
              for(ByteBuffer buf:bigBuffers) buf.clear();
              Path tempFile = Files.createTempFile("FileChannel2GLimitTest",".dat");
              try {
                  System.out.println("Starting to write 3Gb of data...");
                  FileChannel fc = FileChannel.open(tempFile, StandardOpenOption.CREATE,StandardOpenOption.WRITE);
                  long bytesWritten = fc.write(bigBuffers);
                  System.out.printf("Bytes written = %,d\n",bytesWritten);
                  System.out.printf("Total bytes = %,d\n",GB*3L);
              } finally {
                  Files.delete(tempFile);
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Seems like calling write 3 times with 1Gb each works fine

       ByteBuffer bigBuffer = ByteBuffer.allocateDirect(GB);
              bigBuffer.clear();
              Path tempFile = Files.createTempFile("FileChannel2GLimitTest",".dat");
              try {
                  System.out.println("Starting to write 3Gb of data...");
                  FileChannel fc = FileChannel.open(tempFile, StandardOpenOption.CREATE,StandardOpenOption.WRITE);
                  long bytesWritten = fc.write(bigBuffer);
                  System.out.printf("Bytes written = %,d\n",bytesWritten);
                  bigBuffer.clear();
                  bytesWritten = fc.write(bigBuffer);
                  System.out.printf("Bytes written = %,d\n",bytesWritten);
                  bigBuffer.clear();
                  bytesWritten = fc.write(bigBuffer);
                  System.out.printf("Bytes written = %,d\n",bytesWritten);
                  System.out.printf("Total bytes = %,d\n",GB*3L);
                  fc.close();
              } finally {
                  Files.delete(tempFile);
              }

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              bpb Brian Burkhalter
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: