8

Why do I get this error when I run this program? This occurs after random iterations. Usually after the 8000th iteration.

public static void main(String[] args)
{
    FileWriter writer = null;
    try
    {
        for(int i = 0; i < 10000; i++)
        {
            File file = new File("C:\\Users\\varun.achar\\Desktop\\TODO.txt");

            if(file.exists())
            {
                System.out.println("File exists");
            }
            writer = new FileWriter(file, true);
            writer.write(i);
            System.out.println(i);
            writer.close();
            if(!file.delete())
            {
                System.out.println("unable to delete");
            }

            //Thread.sleep(10);
            //writer = null;
            //System.gc();
        }
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        if(writer != null)
        {
            try
            {
                writer.close();
            }
            catch(IOException e)
            {
                e.printStackTrace();
            }
        }
    }
}

After the exception occurs, the file isn't present. That means the it is deleting, but FIleWriter tries to acquire the lock before that, even though it isn't a multi threaded program. Is it because the Windows isn't deleting the file fast enough, and hence the FileWriter doesn't get a lock? If so, then file.delete() method returns before windows actually deletes it?

How do i resolve it, since i'm getting a similar issue during load testing my application.

EDIT 1: Stacktrace:

java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)     
at java.io.FileOutputStream.openAppend(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
    at java.io.FileWriter.<init>(FileWriter.java:61)

EDIT 2 : Added file.exists() and file.delete conditions in the program. and the new stacktrace:

7452
java.io.FileNotFoundException: C:\Users\varun.achar\Desktop\TODO.txt (Access is denied)
    at java.io.FileOutputStream.openAppend(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
    at java.io.FileWriter.<init>(FileWriter.java:90)
    at com.TestClass.main(TestClass.java:25)

EDIT 3 Thread dump

TestClass [Java Application]    
    com.TestClass at localhost:57843    
        Thread [main] (Suspended (exception FileNotFoundException)) 
            FileOutputStream.<init>(File, boolean) line: 192    
            FileWriter.<init>(File, boolean) line: 90   
            TestClass.main(String[]) line: 24   
    C:\Users\varun.achar\Documents\Softwares\Java JDK\JDK 6.26\jdk\jre\bin\javaw.exe (09-Nov-2011 11:57:34 PM)  

EDIT 4 : Program runs successfully on different machine with same OS. Now how do i ensure that the app with run successfully in the machine it is deployed in?

Varun Achar
  • 14,781
  • 7
  • 57
  • 74

9 Answers9

4

On any OS you can have only a certain number of open files/threads at a stretch. You seem to be hitting your OS limit. Try setting file to null inside the loop.

isobar
  • 1,165
  • 8
  • 10
  • `file = null; writer = null; System.gc();` solves the problem. `System.gc()` is crucial. – Varun Achar Nov 11 '11 at 12:45
  • 2
    Well... Setting file and writer variables to null doesn't change anything, because they will be out of scope when you exit the loop (to go to the next file) anyway. And System.gc() is only a *suggestion* for the JVM to perform garbage collection, it doesn't guarantee that it will do anything. so this is not a proper solution, sorry. – Paul Jan 30 '13 at 10:55
2

I have had the same issue, a java program (single threaded) that opens, deleted then re-opens the same file continuously.

On some windows systems we get the same issue as reported here, on Linux, Solaris, and various other windows systems it works fine.

Traceing the program with SysInternals Process Monitor (now MS) its clear the delete is done first, at the OS level, and clear the subsequent open fails with PENDING DELETE status.

So there seems to be some slight delay at the OS/NTFS/Disk level before the file is actually deleted, and that seems to be the cause of the random failure in our case.

As a workaround, I changed the .delete() call to instead just write over the top of it new FileWriter(file) and that seems to be working.

The problem did not occur on all systems, one specific model that would always fail, all be it after not fixed number of loops, was a Windows 7 / Dell Lattitude E6420 with WD Smartdrive, whereas my Windows 7 / Dell precision M4600 (with solid state drive) or T3400 with Linux I have never had the issue.

Cheers - Mark

Mark O'Donohue
  • 681
  • 5
  • 4
2

If I understand your stack trace correctly, the exception is coming when trying to create a new FileWriter. It's impossible to know the reason without investigating a bit further.

  • Return values may tell something. Especially, check what File.delete() returns.
  • Before trying to create new FileWriter, check what File.exists() returns.

If the previous delete() returns true and the exists() right after it also returns true, in a single-threaded program, then it's indeed something weird.

Edit: so it seems that deletion was successful and the file didn't exist after that. That how it's supposed to work, of course, so it's weird why FileWriter throws the exception. One more thought, try checking File.getParentFile().canWrite(). That is, do your permissions to write to the directory somehow disappear.

Edit 2:

Don't get the error on a different machine with the same OS. Now how do i make sure that this error won't come in the app where it'll be deployed?

So far you have one machine that works incorrectly and one that works correctly. Maybe you could try it on even more machines. It's possible that the first machine is somehow broken and that causes errors. It's amazing how often digital computers and their programs (I mean the OS and Java, not necessarily your program) can be just a "little bit broken" so that they work almost perfectly almost all of the time, but fail randomly with some specific hardware & use case - usually under heavy load - similar to how incorrect multi-threaded programs can behave. It doesn't have to be your fault to be your problem :-)

Frankly, the only way to make sure that errors won't come up in machine X is to run the program on machine X. Unusual stuff such as creating and deleting the same file 8000 times in rapid succession is prone to errors, even though it "should" work. Computers, operating systems and APIs are not perfect. The more unusual stuff you do, the more often the imperfections will realize themselves, because unusual usage is generally less thoroughly tested than everyday operations.

Joonas Pulakka
  • 36,252
  • 29
  • 106
  • 169
1

Can you conditionally try to write to the file ?

Using file.exists and then writing to it, so you can potentially avoid any other issues. Hard to say from this exception.

http://download.oracle.com/javase/6/docs/api/java/io/File.html#exists()

Could you also post a thread dump at that point, just to debug it further.

Please flush the writer, before writing again.

r0ast3d
  • 2,639
  • 1
  • 14
  • 18
  • Doesn't help. The line after `if(!file.delete())` doesn't execute. Neither does `if(file.exists())` which is present before creating the `FileWriter` – Varun Achar Nov 10 '11 at 07:44
  • Okay, please flush the writer every time, that should fix it. Updating answer also. – r0ast3d Nov 10 '11 at 16:07
  • According to docs, `close()` *closes the stream, flushing it first.* So explicit flushing should make no difference here. – Joonas Pulakka Nov 11 '11 at 08:43
1

It may be a long shot, but, can you try to work with a file that is NOT directly sitting on the Desktop. Instead of:

"C:\\Users\\varun.achar\\Desktop\\TODO.txt"

Try:

"C:\\Users\\varun.achar\\SomeOtherDirectory\\TODO.txt"

OS may be killing you here with all the Desktop hooks...

EDIT based on the comments:

  • Are there any scheduled jobs running on the "bad" machine?
  • Instead of debugging the environment, do you have a sys admin to do that?
  • Does this work on a clean Windows install? [95% chance it will]
  • Since the root cause seems to be environment, instead of solving a Windows configuration problem, would you be able to move forward with other tasks, and leave it to someone who keeps the list of discrepancies between the systems?
Community
  • 1
  • 1
tolitius
  • 22,149
  • 6
  • 70
  • 81
  • The actual file that my app is writing to is in some other directory. This program is just recreating the error. – Varun Achar Nov 10 '11 at 07:34
  • I just ran it on OS/X => runs fine. Even with 100K iterations. ( java version "1.6.0_26" ). I would still try to change the directory to something ELSE and try again. – tolitius Nov 10 '11 at 07:40
  • 1
    can you try it on different OS, different physical machine? ( you can use [VirtualBox](https://www.virtualbox.org/) or just ssh somewhere where Java is installed ) – tolitius Nov 10 '11 at 07:56
  • Don't get the error on a different machine with the same OS. Now how do i make sure that this error won't come in the app where it'll be deployed? – Varun Achar Nov 10 '11 at 08:06
0

I just had the same problem (FileWriter & Access Denied).

My guess for the reason: Windows 7 had put a lock on the file because a preview of the file content was shown in an Explorer window (the file was selected in the window).

Solution: I de-selected the file in the Explorer window. And the IOException was gone.

0

These are the scenerios you should handle before deleting a file http://www.java2s.com/Code/Java/File-Input-Output/DeletefileusingJavaIOAPI.htm

at least check for return value in your program.

Azodious
  • 13,752
  • 1
  • 36
  • 71
  • Doesn't help. The line after `if(!file.delete())` doesn't execute. Neither does `if(file.exists())` which is present before creating the `FileWriter` – Varun Achar Nov 10 '11 at 07:44
  • Try something weired. Try same program after chagning location of file and change the file name too. – Azodious Nov 10 '11 at 07:49
  • is the iteration count also same every time after which the exception occurs? – Azodious Nov 10 '11 at 07:53
  • when you get the exception try to create `FileWriter` again in catch block. with same name and different also. – Azodious Nov 10 '11 at 07:56
0

Thanks folks for help me out but this is how it got resolved finally.

public static void main(String[] args)
    {
        FileWriter writer = null;
        try
        {
            for(int i = 0; i < 10000; i++)
            {
                File file = new File("C:\\tenant-system-data\\abc.txt");
                if(!file.getParentFile().canWrite())
                {
                    System.out.println("parent file error");
                }
                if(file.exists())
                {
                    System.out.println("File exists");
                }
                int count = 0;
                while(count++ < 5)
                {
                    try
                    {
                        file.createNewFile();
                        break;
                    }
                    catch(IOException e)
                    {
                        try
                        {
                            Thread.sleep(100);
                        }
                        catch(InterruptedException e1)
                        {
                            e1.printStackTrace();
                        }

                    }
                }
                writer = new FileWriter(file, true);
                writer.write(i);
                System.out.println(i);
                writer.close();
                if(!file.delete())
                {
                    System.out.println("unable to delete");
                }

                //Thread.sleep(10);
                //writer = null;
                //System.gc();
            }
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(writer != null)
            {
                try
                {
                    writer.close();
                }
                catch(IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
Varun Achar
  • 14,781
  • 7
  • 57
  • 74
-2

You have delete permission in the directory but not create permission.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • The error is coming in the > 8000th iteration, that means it is deleting and creating the first 8000+ times. – Varun Achar Nov 10 '11 at 07:28
  • 1
    @VarunAchar If you are really creating > 8,000 files in one session I would question your design. You should be using a database. – user207421 Nov 10 '11 at 09:33
  • Not really creating 8000 files.. one single files is getting creating and deleted over and over again. I'm doing this for actually filling up my DB for load testing. The file is used as DB failover feature, to maintain the consistent state between DB and lucene. – Varun Achar Nov 10 '11 at 10:02