JarURLConnection.getJarFile() resource leak when file is not found

Peter Levart peter.levart at gmail.com
Tue Aug 25 17:34:38 UTC 2015


You're right, Neon!

I thought I saw close() somewhere in JarURLConnection, but it seems I 
saw it somewhere else.

Peeking at code, I think it would help if you did:

jarUrlConnection.setUseCaches(false);

before invoking:

jarUrlConnection.getJarFile()/getJarEntry()/connect();


In case caches are not used and the entry is not found in jar file, 
exception is thrown, but JarFile is closed before that.

In case caches are used, JarFile is left open and cached so that next 
time you request an entry from an URL pointing to the same jar file, it 
is already open. This speeds things up when requesting multiple 
resources from the same JarFile, but you loose explicit management of 
JarFile(s).

You could use JarFile API directly and mange it's life-cycle yourself, 
without using URL(Connection), but then you would not be able to use the 
fancy jar URLs...

Regards, Peter

On 08/25/2015 04:27 PM, Neon Ngo wrote:
> There are no close(), disconnect(), or similar method on 
> java.net.JarURLConnection nor it's super class (java.net.URLConnection).
>
> My sample test program will close the resource when searching for an 
> "existing" file inside the jar file.
> It only has resource leak (open file descriptor) when searching for a 
> non-existing file inside the jar file.
>
> Regards,
>
> Neon
>
>
> On Fri, Aug 21, 2015 at 5:19 PM, Peter Levart <peter.levart at gmail.com 
> <mailto:peter.levart at gmail.com>> wrote:
>
>
>
>     On 08/17/2015 04:02 PM, Neon Ngo wrote:
>>     The test program below shows a 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.
>>
>>     Warning, this test program will try to delete the input file, so use with a "temporary" copy of an existing jar file.
>>
>>     This happens under all current Oracle and OpenJDK Java versions: 6, 7, and 8 (I have not tried beta versions of 9).
>>     I could not find a matching BUG for this issue on both the Oracle and OpenJDK websites.
>>     So would like to start the conversation here since my submission on the Oracle website almost a month ago seems to have been lost.
>>
>>     Anyone know of a workaround for this issue?
>
>     Hi Neon,
>
>     Have you tried closing the JarURLConnection before trying to
>     delete the jar file?
>
>     Regards, Peter
>
>
>>     Regards,
>>
>>     Neon
>>     === test.java ===
>>     package nxm.test.lib;
>>
>>     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);
>>        }
>>     }
>>     === end test.java ===
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/net-dev/attachments/20150825/9b32295a/attachment.html>


More information about the net-dev mailing list