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

File.renameTo() may not natively do copy-and-delete but must do rename

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Cannot Reproduce
    • Icon: P4 P4
    • None
    • 5.0
    • core-libs
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.5.0_08"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
      Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      A DESCRIPTION OF THE PROBLEM :
      java.io.File.renameTo()'s native implementation on Windows XP is not done by calling the OS's internal rename() command, but instead seems to be implemented like "copy(),delete()". The problem is that, when some process (e. g. NOTEPAD.exe) has a lock on that file, you will get an empty new file, while the old one still exists. Now remove the lock, try the same thing again, and it will fail, because now there is an empty file with that name already. "rename" is an atomic operation in almost any OS, and it should be atomic on Java, too.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Start "NOTEPAD.exe C:\x.txt", when it asks to create the file, say "OK". Type a few characters, then press SAVE (CTRL+S).
      Start a Java program that does the following lines:
      File a = new File("C:\\x.txt");
      a.isRead()
      a.isWrite()
      a.renameTo(new File("C:\\y.txt"));
      Close NOTEPAD.exe


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      a.isRead() should return true
      a.isWrite() should return false
      a.renameTo() should return false
      C:\\y.txt should not get created.
      ACTUAL -
      a.isRead() returns true (ok)
      a.isWrite() returns true (bug)
      a.renameTo() return false (ok)
      C:\\y.txt gets created, is 0 Bytes large. (bug)

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      No errors got reported.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      public class A {
        public final static void main(final String[] args) throws IOException,
      InterruptedException {
          final File a = new File("C:\\x.txt");
          if (a.exists()) a.delete();
          a.createNewFile();
          FileOutputStream s = new FileOutputStream(a);
          s.write(123);
          s.close();
          final File b = new File("C:\\y.txt");
          if (b.exists()) b.delete();
          Runtime.getRuntime().exec("NOTEPAD.exe " + a.getPath());
          Thread.currentThread().sleep(5000);
          System.out.println(a.canRead());
          System.out.println(a.canWrite());
          System.out.println(a.renameTo(b));
        }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I didn't find a workaround. It seems it is impossible to get an atomic rename in Java, which is needed for a lot of UNIX legacy systems.

            sherman Xueming Shen
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: