Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8232854

URLClassLoader.close() doesn't close cached JAR file on Windows when load() fails

    Details

    • Subcomponent:
    • Resolved In Build:
      master
    • OS:
      windows

      Backports

        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();
                   }
               }

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

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  robm Robert Mckenna
                  Reporter:
                  shadowbug Shadow Bug
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: