JDK-8232854 : URLClassLoader.close() doesn't close cached JAR file on Windows when load() fails
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 7,8,11.0.5,14
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows
  • Submitted: 2019-10-23
  • Updated: 2021-01-12
  • Resolved: 2020-01-30
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 11 JDK 7 JDK 8
11.0.8-oracle b01Fixed 7u271Fixed 8u261Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
java.net.URLClassLoader.close() doesn't work as expected for JAR archives on 
Windows. 

The system resource held by URLClassLoader (i.e. JAR archive itself) is NOT 
released even when the class loader is closed.  A similar issue has been 
fixed by JDK-6896088.  This issue is regarded as a special case fixed by 
JDK-6896088, which can be observerd when close() is called during exception 
handling of load(). 

Issue reproducible in JDK 14, 11, 8 and 7.  7u131 is the oldest of these. 
Steps to reproduce are below. 

1. Creates a arbitrary JAR file 
> ls 
Main.java Main.class 
> jar tvf sample.jar Main.class 
> ls 
Main.java Main.class sample.jar 

2. Run the Main class.  It does the following: 
  a. Creates URLClassLoader and uses it to load a class from the JAR 
  b. Calls close() when the Exception thrown 
  c. Attempts to delete the JAR, but can not. 

> java.exe --show-version Main 
java 13 2019-09-17 
Java(TM) SE Runtime Environment (build 13+33) 
Java HotSpot(TM) 64-Bit Server VM (build 13+33, mixed mode, sharing) 
java.nio.file.FileSystemException: sample.jar: The process cannot access the 
file because it is being used by another process. 

        at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:92) 
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103) 
        at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108) 
        at java.base/sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:274) 
        at java.base/sun.nio.fs.AbstractFileSystemProvider.delete(AbstractFileSystemProvider.java:105) 
        at java.base/java.nio.file.Files.delete(Files.java:1145) 
        at Main.main(Main.java:21) 

Test code: 
======================================================================= 
import java.io.*; 
import java.net.*; 
import java.nio.file.*; 

public class Main { 
   final static String FILE_NAME = "sample.jar"; 

   public static void main(String args[]) { 
       URLClassLoader loader = null; 
       URL url = null; 
       Path path = Paths.get(FILE_NAME); 
       try { 
           String path_str = path.toUri().toURL().toString(); 
           url = new URL("jar", "", path_str + "!/" + "classes/"); 
           loader = new URLClassLoader(new URL[] { url }); 
           loader.loadClass("DUMMY"); 
       } catch (Exception e) { 
       } finally { 
           try { 
               loader.close(); 
               Files.delete(path); 
           } catch (IOException e) { 
               e.printStackTrace(); 
           } 
       } 

   } 
} 
=======================================================================