Modern programs usually employ operating system memory to handle transient data; however, programs that use large amounts of data (e.g. video editing, video transfer) may need to create temporary files.
Programs need to delete temporary files when the usage is complete or when the programs exit. Some programs create temporary files but then leave them behind - they do not delete them. This can happen because the program crashed or the developer of the program simply forgot to delete them after the program is done with them. This may lead to a disk leak.
In Microsoft Windows the temporary files left behind by the programs accumulate over time and can take up a lot of disk space. Personal workstations with UNIX-based operating systems do not suffer from the same problem because their temporary files are wiped at boot. Servers, however, are affected because they are rarely rebooted.
In this post, I look at different ways to ensure that files created temporarily get deleted automatically in Java.
Creating Temporary Files
Java API File.createTempFile() enables the developer to create a temporary file under the operating system’s temporary directory, predefined by the runtime property “java.io.tmpdir”.
One note for using this API is to check the current user’s access permission on the temporary directory. When a program runs in a plug-in or as a network service, it may not have WRITE permission on local disk.
Forget to check the result of file deletion?
The most straightforward way to delete a temporary file is to call File.delete() immediately after the code is done with the temporary file. However, in practice, the developer may forget to check the result of this API. The API returns a Boolean result False on the deletion failure. When it fails, the developer should find an alternate way to delete the temporary file delayed.
Bind file deletion to garbage collection of reference objects
Sometimes, the developer is not sure at which point the file is out of use, but he knows which object instance is using the file. In such case, it is appropriate to bind the file deletion to its referenced object’s garbage collection.
Apache Commons provides a useful utility FileCleaningTracker to work in this way.
public void track(File file, Object marker)
- Track the specified file, using the provided marker, deleting the file when the marker instance is garbage collected. The normal deletion strategy will be used.
But as we know, the JVM garbage collection does not execute timely as we expect, so please do not set an expectation that this way works perfectly.
If the developer is intending to implement a file cleaner like this, please do not forget to check the file deletion result during the cleanup. Unfortunately, Apache FileCleaningTracker hasn’t checked it. There is still a potential disk leak.
Mark a JVM Shutdown Hook
Java developers are familiar with the API File.deleteOnExit(), which delays to delete the file when JVM terminates normally. Indeed, it is powerful; however, experienced developers do not use it often, as there are some constraints to use it.
- - Is it too late to delete temporary files at the end of the program?
YES to servers. Servers don’t shutdown frequently and it is wrong to resort to this API to delete temporary files.
- - Is there some situation that the file does not get deleted?
YES to WIN32 system. When the file is open, this API fails to delete it on JVM terminates.
Besides these constraints, the developer needs to take care of potential memory leak when using this API. Since Java 6, Sun uses a LinkedHashSet to implement the shutdown hook. This hook expands gradually as long as the JVM is alive and it never shrinks. Java checks the hook only at the time when JVM terminates. Even if the file is deleted before JVM terminates, its information is still kept in the hook. As a result, the hook may lead to memory leak.
As of so many reasons, it is not recommended to use JVM shutdown hook at server side.
Write a custom File Cleaner
In the complex programs, it is not bad to write a custom file cleaner to control the full lifetime of temporary files. Daemon threads are often used to execute the house cleanup periodically.
One note is, it is very important to put logs to the code to track the temporary file’s lifetime.
New Cake in Java 7
The NIO.2 feature in Java 7 brings a lot of useful file I/O functions. One option is to delete the file on close, Files.newOutputStream((Path path, OpenOption... options) where the option can be DELETE_ON_CLOSE. This is a good change that the new Java brings more native functions to Java developers.
When the developer writes a program, firstly think about whether it really necessary to create temporary files in his/her program. There is a trade-off of requisitioning resources between memory and disk, corresponding to their cons and pros. If the answer is YES, the developer should choose or design a temporary file cleanup strategy best fit for the program, and being always keep the logging in mind.