JDK-6896088 : URLClassLoader.close() apparently not working for JAR URLs on Windows
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-10-28
  • Updated: 2019-10-24
  • Resolved: 2011-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b128Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
OPERATING SYSTEM:
Windows XP.  Not reproducible on Solaris.

JDK VERSION:
JDK 7 EA b72 was tested.  Likely begin with b48, when close() was implemented.

PROBLEM DESCRIPTION from Licensee:
Here is the scenario being observed -

1. We have a jar file containing a class.
2. We create a URLClassLoader from a URL that points to that jar file,
  employing the JAR prototcol.
3. We load the class from the jar file via the URLClassLoader.
4. We close the URLClassLoader via URLClassLoader.close().
5. We then try to update/delete the jar file, but cannot.

The result of step 5 is unexpected, and is not what happens if we create a URL using the FILE protocol. If we use the FILE protocol the jar file can be deleted once the loader is closed.

This problem also only occurs on Windows - the jar file is deleted as expected with both FILE and JAR URL protocols on Solaris and Linux.


Testcase is attached.
Example code:

=======================================================================
import java.net.*;
import java.io.*;

public class TestLoader {
   public static void main(String[] args){
       try {
           // Create URL using JAR protocol
           String jarName = ((new File("Sample.jar")).toURI()).toString();
           URL url = new URL("jar", "", jarName + "!/");

           // Alternative code using FILE protocol, which works as expected
           // (jarfile can be deleted after loader is closed)
           //URL url = ((new File("Sample.jar")).toURI()).toURL();

           // Create URLClassLoader from the URL
           URLClassLoader loader = new URLClassLoader(new URL[]{url});
           Class c = loader.loadClass("Sample");

           // Close the URLClassLoader so we can delete/update the jar file
           loader.close();

           // Now try to delete the jar file
           File file = new File("Sample.jar");
           if (file.delete() && !file.exists()) {
               System.out.println(file.getName()+" File Deleted");
           } else {
               System.out.println(file.getName()+" File Not Deleted");
           }
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

Comments
EVALUATION URLClassPath.JarLoader is used to manage loading of classes from file: URLs, but it seems the generic mechanism in the super-class, URLClassPath.Loader is used for loading jar: URLs. This wasn't noticed for the original implementation of URLClassLoader.close. We just need to keep track of the JarURLConnections in Loader and make its close() method cleanup (currently a no-op).
27-07-2010

EVALUATION Looks like a bug. Will fix asap.
26-07-2010