15

My Java application (which is quite a bit of code) does a lot of file operations. At one point in my application, I need to move a file from one location to another and for this I'm using the Files.move method from JDK7.

When I try to do this, I get an error telling me that the file is in use. I know for a fact that it's some part of my code that is locking this resource.

How I force my Java application to release all locks prior to calling the function that moves/renames my file?

If this is not possible, is there an easy way to check which part of my code is locking the file? Trudging through my whole codebase to find unclosed file handles would be a nightmare considering the amount of code there is.

Thanks

DwB
  • 37,124
  • 11
  • 56
  • 82
Mridang Agarwalla
  • 43,201
  • 71
  • 221
  • 382
  • maybe of help: http://stackoverflow.com/questions/4179145/release-java-file-lock-in-windows – Chris Feb 17 '13 at 11:50
  • when a classloader loads a jar file, would this jar file descriptor be hold on forever? or is it differ from implementation to implementation? what about the default class loader? – Sajuuk Jun 12 '19 at 05:43

3 Answers3

4

With the help of a debugger you can see all the instances of objects you have in memory (in Netbeans this would be Windows | Debugging | Loaded Classes, and then right click -> Show instances). You can then see all the FileInputStream/FileOutputStream instances you have, and identify those which point to the file you are trying to move. Once you have found a reference to your file, you can see who is still holding the reference.

If there is nobody holding a reference to the file, maybe the instance was discarded without calling close(), and the file would be normally released only after a garbage collection. This makes the previous approach useless, since I think the debugger would automatically garbage collect those streams for you. Maybe you could put a conditional breakpoint inside the stream constructor, and tell it to stop only when the constructor parameter refers to your file.

If you can't find anything, as a last resort you could try to put a couple of System.gc() calls before your move operation, and see if you have any improvement. Clearly this would be only quick-and-dirty fix, to give you some time until you find the actual problem.

Flavio
  • 11,925
  • 3
  • 32
  • 36
  • Actually `File` instances do not hold locks on files. A `File` is just a representation of a file or directory path name. `System.gc()` never closes any open file streams. – ᴇʟᴇvᴀтᴇ Jul 20 '12 at 15:09
  • You are right about `File`. I corrected the answer to refer to `FileInputStream`/`FileOutputStream`. I maintain however my advice about `System.gc()`: the two classes have a `finalize` method which closes the stream, so if you just discarded the object without calling close, a garbage collection might help. – Flavio Jul 23 '12 at 07:32
  • You're right about finalize() in the file streams, so, you're right it could help. It's flaky though! You can't control when garbage collection happens nor what is collected, so you wouldn't want to rely on behavior like this in production. – ᴇʟᴇvᴀтᴇ Jul 23 '12 at 17:15
4

Any solution other than closing streams properly (preferably within a try.. finally block) will be a botch job and will risk making things more unstable than they already are.

I know it's a pain to fix this in a large code-base. If you don't want to trudge through your code, FindBugs is good at locating unclosed streams. There's an Eclipse plugin and you can filter the bugs it finds to just those you're interested in.

ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
4

The File() Object doesnt lock a file, but a FileStream (FileInputStream/FileOutputStream) locks it. So you have to write a HelperClass (e.g. Singleton) for your Streams, wich log all the Streams.

But notice, if You have a leak in your code, it's much better to fix the bug than closing hard all files.

Mirko
  • 1,512
  • 1
  • 12
  • 19