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

channel open/close bug on windows

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P4
    • None
    • 1.4.1_01
    • core-libs
    • None
    • x86
    • windows_2000

    Description



      Name: eaC66865 Date: 03/12/2003


      The code below runs properly on Solaris. It can also be
      made to work on Windows by commenting out the indicated
      lines of code. But with those lines in, the program fails
      under windows 2000.

      THE ERROR
      ---------
      C:\test>"C:\j2sdk1.4.1_01\bin\java.exe" -ea -classpath
      "P:\dev\lab\nio\build\classes\;P:\dev\util\build\classes" NioMappingBug
         read: |test data|
      ch size: 9, buff capacity: 9, pos: 0, lim: 9

      java.io.FileNotFoundException: testFile (Access is denied)
              at java.io.FileOutputStream.open(Native Method)
              at java.io.FileOutputStream.<init>(FileOutputStream.java:176)
              at java.io.FileOutputStream.<init>(FileOutputStream.java:131)
              at NioMappingBug.createOutputStream(NioMappingBug.java:84)
              at NioMappingBug.testTwoWrites(NioMappingBug.java:158)
              at NioMappingBug.run(NioMappingBug.java:41)
              at NioMappingBug.main(NioMappingBug.java:24)
      Failure: The attempt to create an output stream failed
      Exception in thread "main" java.lang.AssertionError
              at NioMappingBug.fail(NioMappingBug.java:179)
              at NioMappingBug.createOutputStream(NioMappingBug.java:88)
              at NioMappingBug.testTwoWrites(NioMappingBug.java:158)
              at NioMappingBug.run(NioMappingBug.java:41)
              at NioMappingBug.main(NioMappingBug.java:24)

      THE CODE
      --------
      import java.io.*;
      import java.nio.*;
      import java.nio.channels.*;
      import java.nio.charset.*;

      import java.util.*;

      public class NioMappingBug {
        String testData = "test data";
        String moreData = "more data";

        File testFile = new File("testFile");

        Charset charset = Charset.forName("UTF-8");
        CharBuffer charBuffer;

        FileChannel testChannel;
        ByteBuffer byteBuffer;

        FileOutputStream outputStream;

        public static void main(String[] argv) {
          NioMappingBug app = new NioMappingBug();
          app.run();
        }

        public void run() {
          setup();
          String result = "";

      //-----------------------------------------------------------
      //INCLUDE THIS TO SEE THE BUG (Length = 18, but data = "test data")
      //COMMENT IT OUT TO SEE THE PROGRAM SUCCEED
          if (testFile.exists()) deleteFile();
          writeFile();
      //-----------------------------------------------------------

          result = readFile(testFile).toString();

          setup();
          testTwoWrites();
          result = readFile(testFile).toString();
      //-----------------------------------------------------------
      //BUG OCCURS HERE
          expectEquals(testData+moreData, result);
      //-----------------------------------------------------------
        }

        public void setup() {
          charBuffer = CharBuffer.allocate(16);
          testChannel = null;
          byteBuffer = null;
          outputStream = null;
        }

        /**
         * Attempt to write to a file that doesn't exist.
         */
        public void writeFile() {
          createOutputStream();
          expect(testFile.exists()); // Creating an output stream also creates
      the file
          testChannel = outputStream.getChannel();
          charBuffer.put(testData); // position=9, limit=16
          charBuffer.flip(); // position=0, limit=9
          byteBuffer = charset.encode(charBuffer);
          try {
            output(byteBuffer, testChannel);
          }
          catch (IOException ioe) {
            ioe.printStackTrace();
            fail("Error writing the file.");
          }
          try {
            outputStream.close(); // closes the channel, as well
          }
          catch (IOException ioe) {
            ioe.printStackTrace();
            fail("Could not close the newly written file.");
          }
        }

        private void createOutputStream() {
          try {
            outputStream = new FileOutputStream(testFile);
          }
          catch (IOException ioe) {
            ioe.printStackTrace();
            fail("The attempt to create an output stream failed");
          }
        }

        /**
         * This is the <i>right</i> way to write.
         *
         */
        public void output(ByteBuffer byteBuffer, WritableByteChannel channel)
          throws IOException {
          int bytesWritten = 0;
          while (bytesWritten < byteBuffer.remaining()) {
            // Loop if only part of the buffer contents get written.
            bytesWritten = channel.write(byteBuffer);
            if (bytesWritten == 0) {
              // Media full? We could do some retries here, or throw an
      exception
              throw new IOException("Unable to write to channel. Media may be
      full.");
            }
          }
        }

        public CharBuffer readFile(File file) {
          CharBuffer resultBuffer = null;
          try {
            FileInputStream stream = new FileInputStream(file);
            FileChannel fileChannel = stream.getChannel();
            int max = Integer.MAX_VALUE;
            if (fileChannel.size() > max) {
              throw new IOException("File too large: " + file.getPath());
            }
            int size = (int) fileChannel.size();
            // Mapped read
            byteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0,
      size);
            // // This code solves the problem
            // byteBuffer = ByteBuffer.allocate(size);
            // while (byteBuffer.hasRemaining()) {
            // int bytesRead = fileChannel.read(byteBuffer); //
      increments position
            // if (bytesRead == 0) {
            // throw new IOException("Read failure: " +
      file.getPath());
            // }
            // }
            // byteBuffer.flip(); // position -> 0, limit -> capacity
            resultBuffer = charset.decode(byteBuffer);
            stream.close(); //closes the associated channel as well
            byteBuffer = null; // attempt to "unmap" the buffer
            report(" read: |" + resultBuffer.toString() + "|");
            report("ch size: " + size + ", buff capacity: " +
      resultBuffer.capacity()
                   + ", pos: " + resultBuffer.position() + ", lim: " +
      resultBuffer.limit()
                   + "\n");
          }
          catch (IOException ioe) {
            ioe.printStackTrace();
            fail("readFile: Error reading file: " + testFile.getPath());
          }
          return resultBuffer;
        }

        public void report(String s) {
          System.out.println(s);
        }

        public void deleteFile() {
          boolean success = testFile.delete();
          if (!success) {
            fail("Delete failed: "+ testFile.getPath());
          }
          expect(!testFile.exists());
        }

        public void testTwoWrites() {
          createOutputStream();
          testChannel = outputStream.getChannel();
          charBuffer.put(testData); // position=9, limit=16
          charBuffer.flip(); // position=0, limit=9
          try {
            byteBuffer = charset.encode(charBuffer);
            testChannel.write(byteBuffer);
            charBuffer.clear();
            charBuffer.put(moreData);
            charBuffer.flip();
            byteBuffer = charset.encode(charBuffer);
            testChannel.write(byteBuffer); // do the 2nd write
            outputStream.close(); // closes the channel, as well
          }
          catch (IOException e) {
            fail("TwoWritesToNonAppendedFile: Error during I/O");
          }
        }

        public void fail(String msg) {
          System.out.println("Failure: "+msg);
          assert false; // sets up a linked stack trace in the CodeGuide IDE
          System.exit(0);
        }

        public void expect(boolean condition) {
          if (condition) return;
          System.out.println("Expected condition failed");
          assert false; // sets up a linked stack trace in the CodeGuide IDE
          System.exit(0);
        }

        public void expectEquals(String expected, String actual) {
          if (expected.equals(actual)) return;
          System.out.println("Comparison failed");
          showDiff(expected,actual);
          assert false; // sets up a linked stack trace in the CodeGuide IDE
          System.exit(0);
        }

        /**
         * Displays the expected and actual string values, like this:<pre>
         * expected: |....the expected string here....|
         * actual: |....the actual string here....|
         * </pre>
         * (The vertical bars help to clarify things when NLs or whitespace
         * characters are present in the strings.)
         */
        protected void showDiff(String expected, String actual) {
          System.out.println("expected: |"+expected+"|");
          System.out.println(" actual: |"+actual+"|");
        }

      }

      ======================================================================

      Attachments

        Issue Links

          Activity

            People

              mmcclosksunw Michael Mccloskey (Inactive)
              earmstrosunw Eric Armstrong (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: