JDK-8037394 : ZipFileSystem leaks file descriptor when file is not a valid zip file
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7u51
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux_ubuntu
  • CPU: x86_64
  • Submitted: 2014-03-06
  • Updated: 2024-07-19
  • Resolved: 2015-01-22
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 9
9 b48Fixed
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0_51"
OpenJDK Runtime Environment (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.13.10.1)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux mhassert 3.11.0-17-generic #31-Ubuntu SMP Mon Feb 3 21:52:43 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

EXTRA RELEVANT SYSTEM CONFIGURATION :
zipfs.jar containing package "com/sun/nio/zipfs" must be in classpath.
Using Ubuntu, this is provided by the package "openjdk-7-jre-headless"

A DESCRIPTION OF THE PROBLEM :
Summary:
When com.sun.nio.zipfs.ZipFileSystemProvider is present, all calls to java.nio.file.FileSystems.newFileSystem() for non-zip files leak an open file descriptor.

Details:
- When one calls java.nio.file.FileSystems.newFileSystem() for an existing file, all installed FileSystemProviders are checked by calling .newFileSystem() on them.
- com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem() checks whether ZipFileSystem is applicable by trying to create a new Instance of it.
- The constructor ZipFileSystem() opens in its second last line a new Channel to the file:
this.ch = Files.newByteChannel(zfpath, READ);
- In its last line it tries to access the zip content, aborting with an exception if not successfull:
this.cen = initCEN();
- In case of an exception the channel "this.ch" is never closed.

Solution:
I propose wrapping the last line in a try-catch-rethrow block, closing the channel in case of an exception.

Note on bug priority:
I am aware that ZipFileSystem is merely a demo and not an integral part of jre. But ironically this bug does not affect users of ZipFileSystem. It is a show-stopper for everyone using java.nio.file.FileSystems.newFileSystem() for any other kind of custom file system. It is enough to have ZipFileSystem on your system.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Steps to reproduce:
- Call java.nio.file.FileSystems.newFileSystem() for an existing file that is not a valid zip file. (An empty file will do)
- ProviderNotFoundException is thrown as expected.
- A file descriptor to the file is kept alive. (using Linux, check with lsof | grep PID)
- By repeating this steps you will eventually hit the file descriptor limit of your OS and a FileSystemException is thrown.

See also provided test case.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expect to safely call java.nio.file.FileSystems.newFileSystem() for non-zip files without side effects.
All file descriptors opened by ZipFileSystem and ZipFileSystemProvider should be released when the file is not a zip file.
ACTUAL -
- A file descriptor to the file is kept alive. (using Linux, check with lsof | grep PID)


ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.nio.file.FileSystemException: /tmp/test: Too many open files
	at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
	at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
	at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
	at java.nio.file.Files.newByteChannel(Files.java:315)
	at java.nio.file.Files.newByteChannel(Files.java:361)
	at com.sun.nio.zipfs.ZipFileSystem.<init>(ZipFileSystem.java:129)
	at com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:139)
	at java.nio.file.FileSystems.newFileSystem(FileSystems.java:386)
	at de.abm.dependencies.ZipFileSystemBug.main(ZipFileSystemBug.java:30)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
// file ZipFileSystemBug.java

import java.nio.file.FileSystem;
import java.nio.file.FileSystemException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;

/**
 * @author mhassert
 * 
 */
public class ZipFileSystemBug {
    
    private static final String EXISTING_NON_ZIP_FILE = "/tmp/test";
    
    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        
        Path path = Paths.get(EXISTING_NON_ZIP_FILE);
        int i = 0;
        while (true) {
            try (FileSystem fs = FileSystems.newFileSystem(path, null);) {
                throw new Exception("THIS SHOULD NEVER HAPPEN");
            } catch (final ProviderNotFoundException e) {
                // EXPECTED
                System.out.println(i++);
            } catch (FileSystemException e) {
                // NOT EXPECTED!
                e.printStackTrace();
                throw e;
            }
        }
    }
}

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


Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/7af354d25024 User: lana Date: 2015-01-28 23:16:37 +0000
28-01-2015

URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/7af354d25024 User: sherman Date: 2015-01-22 20:17:42 +0000
22-01-2015