United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-7166379 javax.imageio.ImageIO.read(ImageInputStream) leaks file handlers
JDK-7166379 : javax.imageio.ImageIO.read(ImageInputStream) leaks file handlers

Details
Type:
Bug
Submit Date:
2012-05-04
Status:
Resolved
Updated Date:
2014-04-28
Project Name:
JDK
Resolved Date:
2012-06-27
Component:
client-libs
OS:
linux_ubuntu,os_x
Sub-Component:
javax.imageio
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
7,7u4
Fixed Versions:

Related Reports
Backport:
Duplicate:
Duplicate:

Sub Tasks

Description
FULL PRODUCT VERSION :
java version "1.7.0_04"
Java(TM) SE Runtime Environment (build 1.7.0_04-b21)
Java HotSpot(TM) 64-Bit Server VM (build 23.0-b21, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Mac OS X 10.7.3

EXTRA RELEVANT SYSTEM CONFIGURATION :
Single threaded command line app. Nothing special.

A DESCRIPTION OF THE PROBLEM :
On JDK 1.7, repeated usage of ImageIO.read(ImageInputStream) results in ???Too many open files??? exception.

Also of interest is the process contains about 10,000 POSIX Semaphores at the same time.

Attempting to close the ImageInputStream manually throws an exception that it is already closed.

JDK 1.6.0_31 does not have this issue.

More details: http://stackoverflow.com/q/10441276/43217

REGRESSION.  Last worked in version 6u31

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Repeatedly reading images via ImageIO.read(ImageInputStream) will result in exhaustion of the process's available open file descriptors.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The JavaDocs state that ImageIO.read(ImageInputStream) closes input stream unless null is returned:

http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(javax.imageio.stream.ImageInputStream)

ACTUAL -
FileNotFoundException: "Too many open files"

Over 10,000 POSIX Semaphores in the process:

COMMAND   PID USER   FD     TYPE DEVICE  SIZE/OFF     NODE NAME
                                      ...
java    36809  smm *235r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *236r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *237r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *238r  PSXSEM              0t0          kcms00008FC901624000
java    36809  smm *239r  PSXSEM              0t0          kcms00008FC901624000

ERROR MESSAGES/STACK TRACES THAT OCCUR :
FileNotFoundException: "Too many open files"

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
// Repeatedly executing this code produces it for me.

BufferedImage image = null;
ImageInputStream stream = null;
try {
    stream = new FileImageInputStream(file);
    image = ImageIO.read(stream);

} catch (Exception ex) {
    log.error("Image could not be read: "+file.getPath());

} finally {
    // ImageIO closes input stream unless null is returned
    // http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html#read(javax.imageio.stream.ImageInputStream)
    if (stream != null && image == null) {
        try {
            stream.close();
        } catch (IOException ex) {
            log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
        }
    }
}

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

CUSTOMER SUBMITTED WORKAROUND :
// I expected the results to be the same as executing this code (which works fine):

BufferedImage image = null;
InputStream stream = null;
try {
    stream = new FileInputStream(file);
    image = ImageIO.read(stream);

} catch (Exception ex) {
    log.error("Image could not be read: "+file);

} finally {
    if (stream != null) {
        try {
            stream.close();
        } catch (IOException ex) {
            log.error("ERROR closing image input stream: "+ex.getMessage(), ex);
        }
    }
}

                                    

Comments
EVALUATION

This fix reports a leak of file handlers on macosx. It mentioned two ways to leak handlers:
 via ImageIO.read(ImageInputStream), and via semaphores.

 I do not observe the first leak: we explicitly close input stream if we found an appropriate reader,
 and this is enough (at least on 1.7.4) to release file handles.

 However, in case of semaphores we leak tons of handles: we perform color conversion
 for each line of jpeg image, and each time we create a semaphore (because we see 2 or more
 CPU installed on the system), then we reduce number of separate tasks down to 1 (because
 we have single scan line to process) and due to this never unlink the semaphore.

 The same problem is present on Linux systems, but in less degree because we occupy single
 file handle per named semaphore, whereas on macosx we always occupy new file handle.

 Suggested fix just postpones the creation of named semaphore until we clarify the number of
 separate tasks, so, now we do not create semaphores for image reading and simple color
 conversions (like ColorSpace.toRGB()). Beside this, now we use pSem pointer as a trigger
 for the semaphore destruction.
                                     
2012-06-14
SUGGESTED FIX

http://sa.sfbay.sun.com/projects/java2d_data/8/7166379/
                                     
2012-06-14



Hardware and Software, Engineered to Work Together