views:

495

answers:

7

Hi I am using a lot of temporary files in java and my problem is that they do not get deleted.

Without having to implement my own handling of temporary file management (not hard I grant you but I am lazy plus with so many things to do If I can save reinventing the wheel for this all the better) is there a way to ensure the temp files on disk will get deleted in a fairly regular fashion.

1 - using File tmp = File.createTempFile(), sure I can say tmp.deleteOnExit() but If the thing runs in a service the only way it exits is when it either crashes (happens rarely), or when the system crashes (like when the drive is completely full of temp files and topples the cluster... oops !)

Ideally, the instances created gets collected at some point by the garbage collector, and since there is a LOT of idle time in the application it would just be dandy if the GC could, well, finish it`s cleanup and actually delete the file on disk as well when dereferencing the instance from memory.

the only way I see for now is overload the File class and add a finalized method... If I do that might as well go with my own temp file manager !

So long story short, can I use the Garbage Collector to clean up system resources (ie files) as well ?


Thank you all for your answers. I accepted Christoffer's as it was the simplest to implement and is what I ended up doing.

I guess being cleaned up after for so many years made me forget the basic housekeeping I was though to do the hard way in the good'ol days of C++.

+1  A: 

You might want to look into PhantomReference:

Phantom reference objects, which are enqueued after the collector determines that their referents may otherwise be reclaimed. Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.

Robert Munteanu
yes Phantom references seems to be what I am after here where I could "hook" in the GC`s workflow and intervene on some objects.However implementing it will most likely be more complex and less sure than just managing them manually, I guess I will roll-up the sleeves and just do it !
Newtopian
+2  A: 

Relying on an event to fire when your class is destroyed is not going to be foolproof, and may leave files behind.

I think the simplest and most reliable way to achieve cleanup of your temp files is as follows:

  • Write an event handler for when your program closes to clean up any files you had open during your current session.
  • Write a procedure that will run when your program starts, which deletes any temp files in this folder which are older than 24 hours.

With this approach you need not fear if your program crashes for some reason and leaves temp files behind, and you also don't need to worry about the program deleting files which are still in use.

Bork Blatt
ACtually the event on close comes free for temp files... File.deleteOnExit does just that without any extra code... problem is the application does not exit ! at least not on it`s own where this code could have effect.This just leaves me with the batch erase from time to time.
Newtopian
+1  A: 

Garbage collection is the wrong namespace for this type of information handling.

The following point should be enough to handle temp files.

  1. You should try to delete the file directly after you do not use the file anymore. A finalize block can handle this.

  2. DeleteOnExit you should use.

  3. You can create your temporary files in a special temp directory. This temp directory you can delete when the application is launched and closed, to be sure, that no temp files are existing after the application is closed.

Markus Lausberg
1 - finalize to be useful must be on a class that will be claimed by the GC, thus in this case I will have to override the File class from Java, which I am reluctant to do.2- I expressly stated that deleteOnExit will not do, the program, in theory, does not exit... ever3-yep... basically comes back to creating my own handling of temp files... I taught of the GC since it would be natural of it to also claim these resources, I see it is not so simple.
Newtopian
A: 

Well you could make a wrapper for a file which uses a finalizer to delete your file when the object is garbage collected.

But finalizers don't get called in any predictable way so I really wouldn't recommend that at all.

John Burton
yes that would work but I would need to extend the File class + as you and others have stated not overwhelmingly reliable.
Newtopian
+1  A: 

Garbage collector is not a place to do this kind of resource free up. Please see these two articles below on how to release resources in Java http://c2.com/cgi/wiki?ReleasingResourcesInJava And also the performance issues with Java finalizers. They may give some insight and understanding as to how it should be used. http://www.enyo.de/fw/notes/java-gc-finalizers.html

Priyank
good reading.. thanks
Newtopian
it's my pleasure
Priyank
+1  A: 

Sure you can. The question is whether you really want to :)

I've actually encountered this problem in the wild; as you noticed, cleaning up temporary files with deleteOnExit() is useless when running a service rather than an application. I found that the most stable solution was to restructure the program flow such that temporary files were created on a per-task basis, and explicitly deleted when no longer needed.

If you do it any other way, i.e. if the program is unable to conclude whether a temporary file should be kept or discarded at any point during the execution, you might have a design problem. Wrapping files in some manager harness would just postpone the "real" solution ;)

Christoffer
+1  A: 

The garbage collector is not useful for such things. It is designed for memory-management and that can have many downsides.

  • Your object could be collected long time after the file is no longer in use.
  • Your object isn't guaranteed to be collected at all.

Both thing happen especially often, if Java is started with a big heap-size - a thing that on server-side is not unusual.

At some point in your program you have to close the Streams on that file (otherwise you would eat up system-file-handles, that makes the system unusable, I did that already). At the point you close the streams you could also delete the associated file. That is the cleanest way.

Mnementh