JDK-4405789 : JAR files, modified on disk, are not reloadable until old URLClassLoader's GC'd
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_2.6
  • CPU: x86
  • Submitted: 2001-01-18
  • Updated: 2001-11-14
  • Resolved: 2001-11-14
Related Reports
Duplicate :  
Relates :  
Description
In the NetBeans/Forte for Java application, many URLClassLoader's can be created loading different modules from JAR files. For development-time testing and for other reasons, it is sometimes desirable to reload a JAR file (with new contents) in a new classloader. Unfortunately, it seems that if the old URLClassLoader is not garbage-collected, something in the JRE "holds on" to the old *.jar file handle and the new classloader loads the same old contents, not the contents on disk. If the classloader is garbage-collected (sometimes difficult to enforce), then it seems to work OK.

Also on Windows under JDK 1.2.2 (but not 1.3), if the old loader is not garbage-collected, the JVM keeps a file lock on the archive file and it is impossible to write to it. On Windows with 1.3 or with Unix, this does not happen.

I made a test app which loads a class from a JAR and runs it; tries to garbage-collect the class and its classloader; modified the byte contents of the JAR file; and tries to reload it. It is easy to run with the Ant tool, else you can run the right Java command by hand. When garbage collection is turned on, each disk modification is correctly picked up. With forced GC off, it will display the same test string over and over until a GC happens to occur (if you run it through say 1000 iterations). Also under Windows with JDK 1.2.2 with GC off the modification will fail because there is a file lock on the JAR.

I guess that java.util.zip.ZipFile or similar is using file handles in such a way that it does not reload them, even if the ZIP/JAR changed on disk (incl. modification time). Is there a reason for this, and can it be fixed to always reopen the archive file (at least if it has a new modification time), whether or not an existing ZipFile object (I guess, via URLClassPath and URLClassLoader) is referring to it?

Comments
WORK AROUND Can be worked around by not loading the archive directly, rather making a temp file (delete-on-exit) which is a copy of it and loading from that; then no lock is held on the original archive and it is possible to make new classloaders with the new contents.
11-06-2004

PUBLIC COMMENTS This has now been fixed. To avoid caching in JarURLConnection which is used by the URLClassLoader, call URLConnection.setDefaultUseCaches(false) on any instance of URLConnection. (this method should have been been static but its is not). ###@###.### 2001-11-13
13-11-2001

EVALUATION This has now been fixed. To avoid caching in JarURLConnection which is used by the URLClassLoader, call URLConnection.setDefaultUseCaches(false) on any instance of URLConnection. (this method should have been made static but its is not). ###@###.### 2001-11-13
13-11-2001