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

URLConnection.getLastModified() leaks file handles for jar:file and file: URLs

XMLWordPrintable

    • b04
    • x86
    • windows_7
    • Verified

      FULL PRODUCT VERSION :
      java version "1.6.0_20"
      Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
      Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Ubuntu 7.04
      Linux coconut 2.6.20-16-server #2 SMP Fri Aug 31 01:01:45 UTC 2007 i686 GNU/Linux

      also reproduced on:
      Windows 7 Professional 64-bit
      Microsoft Windows [Version 6.1.7600]

      A DESCRIPTION OF THE PROBLEM :
      Using the getLastModified() call on a URLConnection for jar:file: or file: URLs causes file handles to remain open. When performing many of these calls in quick succession, the operating system can easily hit the open file handles limit. E.g., on an Ubuntu Linux install, the system-wide open file limit is 1024 by default, out of which a large portion may already be consumed by other processes.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Open a jar:file: URL connection. E.g. run getClass().getResource("META-INF/MANIFEST.MF").openConnection(). This returns a sun.net.www.protocol.jar.JarURLConnection.

      On this URL connection, run getLastModified().

      This runs, in sequence,
      java.net.URLConnection.getHeaderFieldDate(),
      sun.net.www.protocol.jar.JarURLConnection.getHeaderField(),
      sun.net.www.protocol.file.FileURLConnection.getHeaderField(),
      sun.net.www.protocol.file.FileURLConnection.initializeHeaders(),
      sun.net.www.protocol.file.FileURLConnection.connect().

      This last call, opens a FileInputStream which is not closed, further on.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The getLastModified() call does not cause a file handle to be opened, or closes it before returning.
      ACTUAL -
      A file handle remains open.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // NOTE: This code snippet should be run on a platform where the 'lsof' command is available (e.g. Linux).
      // The problem is present on Windows, but it is not as easy to show the number of open files to expose the problem.

      private void exposeFileHandleLeakOnJarUrlConnection() throws InterruptedException, IOException {
      URL jarUrl = LastModifiedBugExposer.class.getResource("/META-INF/MANIFEST.MF");

      printNumberOfOpenFiles("jar");
      for (int i = 0; i < 10; ++i) {
      jarUrl.openConnection().getLastModified();
      printNumberOfOpenFiles("jar");
      }
      }

      private void printNumberOfOpenFiles(String method) throws InterruptedException, IOException {
      Process process = Runtime.getRuntime().exec("lsof");
      BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
      int lines = 0;
      while (reader.readLine() != null) {
      ++lines;
      }
      reader.close();
      process.waitFor();

      System.out.println("Number of open files (" + method + "): " + lines);
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use the following code to obtain the last modified date of a JAR file:
      new File(((JarURLConnection)conn).getJarFile().getName()).lastModified()

            michaelm Michael McMahon
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: