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

(fs) FileChannel.transfer{From,To} transfer too many bytes w/ non-file channels

XMLWordPrintable

    • rc
    • x86
    • windows_nt
    • Verified



      Name: rmT116609 Date: 06/26/2002


      FULL PRODUCT VERSION :
      java version "1.4.1-beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
      Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

      FULL OPERATING SYSTEM VERSION :

      Windows NT Version 4.0 Service Pack 6a

      A DESCRIPTION OF THE PROBLEM :
      When an arbitrary (e.g. anonymous) ReadableByteChannel is
      used with the transferFrom() method of a FileChannel, it
      tries to transfer more data than was requested.

      The buffer that is passed to the read() method of the
      anonymous ReadableByteChannel has more data remaining that
      was requested to be transferred, in the last block.

      This used to work in 1.4.0 and 1.4.0_01, but is now broken
      (note that 1.4.0 has a multitude of other problems related
      to this method, including crashing the JVM, that seem to be
      fixed now).

      REGRESSION. Last worked in version 1.4

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Compile the example code.
      2. Run it, e.g. java TransferBugTest
      3. Watch the output.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected results (this works in JDK 1.4.0):
      The last lines of output should say:

      array.length = 131077, writePosition = 131072, writeLength
      = 5
      count = 131077

      Actual results (this breaks in JDK 1.4.1 beta):
      Instead you get:

      array.length = 131077, writePosition = 131072, writeLength
      = 8192
      Exception in thread "main"
      java.lang.IndexOutOfBoundsException
              at java.nio.Buffer.checkBounds(Buffer.java:454)
              at java.nio.DirectByteBuffer.put
      (DirectByteBuffer.java:292)
              at TransferBugTest$1.read(TransferBugTest.java:28)
              at
      sun.nio.ch.FileChannelImpl.transferFromArbitraryChannel
      (FileChannelImpl.java:534)
              at sun.nio.ch.FileChannelImpl.transferFrom
      (FileChannelImpl.java:572)
              at TransferBugTest.main(TransferBugTest.java:18)

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      Exception in thread "main" java.lang.IndexOutOfBoundsException
              at java.nio.Buffer.checkBounds(Buffer.java:454)
              at java.nio.DirectByteBuffer.put(DirectByteBuffer.java:292)
              at TransferBugTest$1.read(TransferBugTest.java:28)
              at sun.nio.ch.FileChannelImpl.transferFromArbitraryChannel
      (FileChannelImpl.java:534)
              at sun.nio.ch.FileChannelImpl.transferFrom(FileChannelImpl.java:572)
              at TransferBugTest.main(TransferBugTest.java:18)

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.RandomAccessFile;
      import java.io.IOException;
      import java.nio.ByteBuffer;
      import java.nio.channels.FileChannel;
      import java.nio.channels.ReadableByteChannel;

      public class TransferBugTest
      {
          public static void main(String[] args)
              throws IOException
          {
              RandomAccessFile file = new RandomAccessFile("test.dat", "rw");
              file.setLength(131077);

              FileChannel channel = file.getChannel();

              final byte[] array = new byte[131077];
              long count = channel.transferFrom(new ReadableByteChannel()
              {
                  public int read(ByteBuffer buffer)
                  {
                      int writeLength = buffer.remaining();

                      System.out.println("array.length = " + array.length +
                                         ", writePosition = " + writePosition +
                                         ", writeLength = " + writeLength);

                      buffer.put(array, writePosition, writeLength);

                      writePosition += writeLength;

                      return writeLength;
                  }

                  public void close() {}
                  public boolean isOpen() { return true; }

                  private int writePosition = 0;
              },
              0,
              131077);

              System.out.println("count = " + count);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      None, really.

      If you know the number of bytes that should be transferred,
      you can check the number of bytes remaining inside the read
      () method. In general this is not possible of course,
      because the only information being passed as arguments to
      the ReadableByteChannel is the ByteBuffer, and even the
      specification says it should try to read as much data that
      is remaining in the buffer.

      Release Regression From : 1.4.0_01
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Review ID: 158461)
      ======================================================================

            mr Mark Reinhold
            rmandalasunw Ranjith Mandala (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: