JDK-6213298 : File.renameTo() sometimes doesn't work even if the new file name doesn't exist
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 1.4.2_05,5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000,windows_2003
  • CPU: x86
  • Submitted: 2005-01-02
  • Updated: 2011-02-16
  • Resolved: 2009-02-16
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0"
java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Windows 2000 V5.0 Build 2195: SP4

A DESCRIPTION OF THE PROBLEM :
After releasing a File object, another File object for the same file name cannot be renamed immediately.  Here's my work-around that usually works but still sometimes fails.

public class XFile extends File
   {

   /*
   ==============================================================
   ============================================================== *//**
   This method is a cover for File.renameTo(). The motivation for this
   cover method is that with this new version of Java (1.5.0), rename (and
   other file methods) sometimes don't work on the first try. This seems to
   be because file objects that have been closed are hung onto, pending
   garbage collection.

   @return
      true if and only if the renaming succeeded; false otherwise

   @param
      pNewFile is a File object containing the new name for the file.
   *//*
   -------------------------------------------------------------- */
   public boolean renameTo(File pNewFile)
      {
      /*
      ===============================================
      HACK - I should just be able to call renameTo() here and return its
      result. In fact, I used to do just that and this method always worked
      fine. Now with this new version of Java (1.5.0), rename (and other
      file methods) sometimes don't work on the first try. This is because
      file objects that have been closed are hung onto, pending garbage
      collection. By suggesting garbage collection, the next time, the
      renameTo() usually (but not always) works.
      ----------------------------------------------- */
      for (int i=0; i<20; i++)
         {
         if (super.renameTo(pNewFile))
            {
            return true;
            }
         System.gc();
         Util.sleep(50);
         }
      return false;
      }
   }

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
File x = new File("file.x");    // existing file same as File y
File y = new File("file.x");    // existing file same as File x
File z = new File("new.x");  // new file name for non-existing file

//  do I/O ops with File y

y = null;

if (x.renameTo(z)) System.out.println("success");
else System.out.println("failure");



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
should always report success and rename the file.
ACTUAL -
usually reports "failure" and does not rename the file.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
None; unfortunately, File.renameTo() doesn't throw an exception, it just returns "false" when it fails.

REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
File x = new File("file.x");    // existing file same as File y
File y = new File("file.x");    // existing file same as File x
File z = new File("new.x");  // new file name for non-existing file

//  do I/O ops with File y

y = null;


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

CUSTOMER SUBMITTED WORKAROUND :
public class XFile extends File
   {

   /*
   ==============================================================
   ============================================================== *//**
   This method is a cover for File.renameTo(). The motivation for this
   cover method is that with this new version of Java (1.5.0), rename (and
   other file methods) sometimes don't work on the first try. This seems to
   be because file objects that have been closed are hung onto, pending
   garbage collection.

   @return
      true if and only if the renaming succeeded; false otherwise

   @param
      pNewFile is a File object containing the new name for the file.
   *//*
   -------------------------------------------------------------- */
   public boolean renameTo(File pNewFile)
      {
      /*
      ===============================================
      HACK - I should just be able to call renameTo() here and return its
      result. In fact, I used to do just that and this method always worked
      fine. Now with this new version of Java (1.5.0), rename (and other
      file methods) sometimes don't work on the first try. This is because
      file objects that have been closed are hung onto, pending garbage
      collection. By suggesting garbage collection, the next time, the
      renameTo() usually (but not always) works.
      ----------------------------------------------- */
      for (int i=0; i<20; i++)
         {
         if (super.renameTo(pNewFile))
            {
            return true;
            }
         System.gc();
         Util.sleep(50);
         }
      return false;
      }
   }
###@###.### 2005-1-02 13:20:06 GMT

Comments
EVALUATION The renameTo method (like many other java.io.File methods) is exposing the behaviour of the underlying operating system and file system. In this case a rename of an open file on Windows fails with a "sharing violation" which causes the renameTo method to fail and return false. Another issue with renameTo (and other methods) is that it is not specified to throw any exceptions when the rename fails. These, and other many other file system issues, are currently being examined by JSR-203. At a minimum you should expect that the platform will get a more consistent file rename capability that will include exceptions to more clearly indicate the reason why the underlying rename failed.
26-01-2006