JDK-8132359 : Amend JarURLConnection::getJarFile() to return JarFile object reference for nonexistent JAR file entry URL
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 8-pool,9
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • CPU: x86_64
  • Submitted: 2015-07-24
  • Updated: 2021-04-06
  • Resolved: 2021-04-06
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.
Other
tbdResolved
Related Reports
CSR :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
6u45
7u79, 7u70
8u45, 8u51

ADDITIONAL OS VERSION INFORMATION :
Windows 7 64-bit
Windows 7 32-bit
CentOS 6.6 64-bit
RHEL 5.9 32-bit

A DESCRIPTION OF THE PROBLEM :
There is a resource leak in JarURLConnection.getJarFile() when a file is not found.
A FileNotFOundException is thrown and the underlining opened JarFile underneath is not closed.

This test program shows resource leak in java.net.JarURLConnection's getJarFile() when given an non-existent file to lookup in the jar file.

Under Windows, the last printout shows that it is not able to remove the test input jar file. Any input jar file can be used to test this as long as it does not contain "/testNonExistentFile.xyz" in the jar file. 

WARN: test program will try to delete the input file, so use with a "temporary" copy of an existing jar file.

=== test.java ===

import java.io.File;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.JarFile;

public class test {

  public static void getJarFile(String urlstr) throws Exception {
    System.out.println("testing URL: " + urlstr);
    URL url = new URL(urlstr);
    URLConnection urlConnection = url.openConnection();
    if (urlConnection instanceof JarURLConnection) {
      JarURLConnection jarUrlConnection = (JarURLConnection) urlConnection;
      JarFile jarFile = jarUrlConnection.getJarFile();
      System.out.println(" Got JarFile  : " + jarFile);
      System.out.println(" JarFile.name : " + ((jarFile != null) ? jarFile.getName() : ""));
      jarFile.close();
      System.out.println(" Closed JarFile " + jarFile);

    } else if (urlConnection != null) {
      System.err.println(" URLConnection.class: " + urlConnection.getClass());
    }
  }

  public static void main(String[] args) {
    if (args.length < 1) {
      error("Usage: <file.jar>");
    }
    String jarFilename = args[0];
    File file = new File(jarFilename);
    if (!file.exists()) {
      error("input jar file does not exists: " + file);
    }

    String nonExistentFileInJar = "jar:file:" + jarFilename + "!/testNonExistentFile.xyz";
    try {
      getJarFile(nonExistentFileInJar);
    } catch (Exception e) {
      e.printStackTrace();
    }

    boolean result = file.delete();
    System.out.println("Able to remove test jar file? " + result);

    if (!result) {
      error("Unable to remove test jar file: " + jarFilename);
    }
  }

  static void error(String msg) {
    System.err.println(msg);
    System.exit(1);
  }
}


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run test program under Windows with path to an existing jar file (make copy of any jar file as test program will try to delete it). Under Windows when a file is still open (i.e. the resource leak),

create junk.jar
jar cvf junk.jar test.java
java -cp . test junk.jar


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
C:\Users\ntn>\java\java7\bin\java -cp . test junk.jar
testing URL: jar:file:junk.jar!/testNonExistentFile.xyz
java.io.FileNotFoundException: JAR entry testNonExistentFile.xyz not found in junk.jar
        at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:140)
        at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:89)
        at test.getJarFile(test.java:15)
        at test.main(test.java:38)
Able to remove test jar file? true

ACTUAL -
C:\Users\ntn>\java\java7\bin\java -cp . test junk.jar
testing URL: jar:file:junk.jar!/testNonExistentFile.xyz
java.io.FileNotFoundException: JAR entry testNonExistentFile.xyz not found in junk.jar
        at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:140)
        at sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:89)
        at test.getJarFile(test.java:15)
        at test.main(test.java:38)
Able to remove test jar file? false
Unable to remove test jar file: junk.jar


REPRODUCIBILITY :
This bug can be reproduced always.


Comments
The reported problem was fixed by JDK-8264048: The attached reproducer succeeds to delete a jar file on windows platform: java.io.FileNotFoundException: JAR entry testNonExistentFile.xyz not found in junk.jar at java.base/sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:146) at java.base/sun.net.www.protocol.jar.JarURLConnection.getJarFile(JarURLConnection.java:92) at Jdk8132359Test.getJarFile(Jdk8132359Test.java:14) at Jdk8132359Test.main(Jdk8132359Test.java:37) Able to remove test jar file? true
06-04-2021

Tests for each of the API methods were run and the results are recorded in the table below below. If the JCK only triggered a difference on getManifest ... then it would be expected that getJarFile and getMainAttributes would also appear as different in the JCK results ? method JDK15 master build with Proposed change JDK15 master build without proposed change getJarFile * JarFile reference returned FileNotFoundException thrown getJarEntry ** FileNotFoundException thrown. FileNotFoundException thrown getAttributes. FileNotFoundException thrown FileNotFoundException thrown getCertificates FileNotFounfException thrown FileNotFoundException thrown getManifest Mainfest reference returned FileNotFoundException thrown getMainAttributes Attributes reference returned FileNotFoundException thrown getInputStream *** FileNotFoundException thrown FileNotFoundException thrown *. abstract java.net.JarURLConnection method overridden in sun.net.www.protocol.jar.JarURLConnection ** java.net.JarURLConnection method overridden in sun.net.www.protocol.jar.JarURLConnection *** java.net.URLConnection method overridden in sun.net.www.protocol.jar.JarURLConnection
13-05-2020