JDK-6212146 : URLConnection.connect() fails on JAR Entry it creates file handler leak
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 1.4.2,6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_2000
  • CPU: generic,x86
  • Submitted: 2004-12-23
  • Updated: 2012-10-28
  • Resolved: 2006-03-23
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 6
6 b78Fixed
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
If an URL is created with the JAR file notation "jar:file:<file path>!/anInvalidEntry" the following URLConnection.connect() fails with a java.io.FileNotFoundException but the unterlying file handler is not released. This ends up in a resource leak and over time a java.util.zip.ZipeException "Too many files open" can be thrown.

This is a serious problem because there is no way to close the file because no InputStream is returned and therefore theres is no way to close it afterall. I guess whatever is opening the input stream does not close the file in the cause of an exception leaving the object in a broken state.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a bunch of files (on W2K at least 2500)
2. In a loop create URLS using an JAR URL with an invalid entry
3. Open the URL Connection and either call connect() or getInputStream()
4. Wait until you get a ZipException



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
There should be no ZIP exception indicating too many open files because the Input Stream is not returned an so is not closeable.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
14:04:45 ERROR [URLConnectionOnJarFileTestCase] Open Connection failed
java.util.zip.ZipException: Too many open files
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.<init>(ZipFile.java:112)
        at java.util.jar.JarFile.<init>(JarFile.java:127)
        at java.util.jar.JarFile.<init>(JarFile.java:65)
        at sun.net.www.protocol.jar.URLJarFile.<init>(URLJarFile.java:55)
        at sun.net.www.protocol.jar.URLJarFile.getJarFile(URLJarFile.java:40)
        at sun.net.www.protocol.jar.JarFileFactory.get(JarFileFactory.java:63)
        at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.ja
va:85)
        at foo.URLConnectionOnJarFileTestCase.testURLConnectionsOnJarFiles(URLCo
nnectionOnJarFileTestCase.java:76)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
That is an example code:

   public void testURLConnectionsOnJarFiles()
         throws Exception {
      System.out.println( new java.io.File( "." ).getAbsolutePath() );
      String lProperty = System.getProperty( "do.iterations", "10000" );
      int lRepetitions = new Integer( lProperty ).intValue();
      mLog.info( "Start creating copys of the archive, " + lRepetitions + " times" );
      for( int i = 0; i < lRepetitions; i++ ) {
         // Copy the given jar file and add a prefix
         copyFile( BASE_DIR, ARCHIVE_NAME, i );
      }
      mLog.info( "Start opening the archives archive, " + lRepetitions + " times" );
      for( int i = 0; i < lRepetitions; i++ ) {
         // Create ULR
         String lURLPath = "jar:file:./" + i + ARCHIVE_NAME + "!/foo/Test.class";
         URL lURL = new URL( lURLPath );
         // Open URL Connection
         try {
            URLConnection lConnection = lURL.openConnection();
            lConnection.getInputStream();
         } catch( java.io.FileNotFoundException fnfe ) {
            // Ignore this one because we expect this one
         } catch( java.util.zip.ZipException ze ) {
            if( ze.getMessage().equals( "Too many open files" ) ) {
               fail( "Too many open files exception on URL Connection" );
            } else {
               mLog.error( "Open Connection failed", ze );
            }
         } catch( Exception e ) {
            mLog.error( "Open Connection failed", e );
         }
      }
      mLog.info( "Done testing, waiting 20 seconds for checking" );
      Thread.sleep( 20 * 1000 );
   }

   private void copyFile( String pBaseDir, String pArchiveName, int pIndex ) {
      try {
         java.io.File lSource = new java.io.File( pBaseDir, pArchiveName );
         java.io.File lDestination = new java.io.File( ".", pIndex + pArchiveName );
         if( !lDestination.exists() ) {
            lDestination.createNewFile();
            java.io.InputStream lInput = new java.io.FileInputStream( lSource );
            java.io.OutputStream lOutput = new java.io.FileOutputStream( lDestination );
            byte[] lBuffer = new byte[ 1024 ];
            int lLength = -1;
            while( ( lLength = lInput.read( lBuffer ) ) > 0 ) {
               lOutput.write( lBuffer, 0, lLength );
            }
            lInput.close();
            lOutput.close();
         }
      } catch( Exception e ) {
         e.printStackTrace();
      }
   }

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Funny thing tough I can fix the problem by using the same JAR URL but without any entry, creating a new URL Connection, upcasting it to a JarURLConnection, get the Jar File and close this one does the trick for me.
###@###.### 2004-12-23 11:50:13 GMT
Suggested fix from community member schaefa is too large to include in this field.
Please refer to attached file 564048.txt

Comments
EVALUATION Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=12040&forumID=1463
16-03-2006

EVALUATION This will be integrated into b77 of mustang
28-02-2006

EVALUATION 5105410 does not fix this because in this particular case, close() on the stream is not being called, due to the exception being thrown.
01-02-2006

EVALUATION No, this has not been fixed. I will look at the proposed fix from the submitter.
26-01-2006

EVALUATION Looks like a dup of 5105410, which has already been fixed. Assigning to the fixer of that bug for further investigation. ###@###.### 2004-12-23 22:03:45 GMT
23-12-2004