JDK-5041014 : URLClassLoader.getResourceAsStream locks jar files
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.4.2,1.4.2_04
  • Priority: P2
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-05-01
  • Updated: 2010-07-05
  • Resolved: 2010-07-05
Related Reports
Relates :  
Relates :  
Relates :  
Description
To reproduce the problem, on a Windows machine, create a test.jar, and run the following test case in jdb.  Stop at the first println, "test.jar" is now locked and cannot be deleted.

Note that the test is only trying to get a non-existant resource.  Note also that this is only a problem for the Windows platform.

This bug breaks an important functionality in AppServer, because it makes undeployment of a web applications impossible (in Windows), because jar files in it cannot be deleted.  See bug 5004315.  There does not seems to be any workarounds.

% cat Test.java
import java.io.*;
import java.net.*;

class Test {
    public static void main(String args[]) {

        try {
            File jarf = (new File("test.jar")).getCanonicalFile();
            URL urls[] = { jarf.toURL() };
            URLClassLoader loader =
                new URLClassLoader(urls, Test.class.getClassLoader());
            InputStream is = loader.getResourceAsStream("BadName");
            System.out.println("stream is " + is);
        } catch (Exception ex) {
            System.out.println("Error: " + ex);
        }
    }
}


###@###.### 2004-04-30

Comments
EVALUATION URLClassLoader now has a close() method, which is designed to address this problem.
2010-07-05

EVALUATION Looks like the creation of a JarFile would retain a lock to the file. I don't know whether that's the correct behaviour. Reassigning to the T&L team for further evaluation. ###@###.### 2004-05-06 While a jar file is opened, a file descriptor to the file is maintained, so that the file does not have to be continually reopened. This is important for good performance of the JVM. Note that this is business as usual for Windows applications. You cannot replace any supporting files in a Windows application that are in use, by design. An operation like replacing a dll typically requires a reboot on Windows. You can make an argument for both ways of doing things, but Java certainly cannot change the way Windows works. I will likely close this as Will Not Fix. ###@###.### 2004-05-06 The general problem of a program's supporting files being replaced is a known problem. Windows chooses to lock such files, while Unix permits it, at the cost of possibly causing JVM crashes when a zip file being used is replaced unexpectedly. The standard workaround, if you *really* want replaceability, is to always make a defensive copy of the jar file containing the contents you want before opening it. You might not want to pay the cost of that, however. We are very unlikely to want to copy rt.jar every time `java' is invoked. ###@###.### 2004-05-11 5098318 also has to make sure sure JCE tries to clean up everything to allow for GC'ing/unloading correctly. Having a close() would make things easier. ###@###.### 2005-05-26 00:22:38 GMT ###@###.### 2005-05-26 00:52:07 GMT
2005-05-26

SUGGESTED FIX The bug seems to be in sun.misc.URLClassPath$Loader.findResource. In it URL.openConnection() is invoked, but the stream for the connection is not closed.
2004-06-11