The dangers of Javas ImageIO

January 25, 2012 by Michael

Javas ImageIO works… well, most of the time. It contains some unfixed, jpeg related bugs, but it works.

It may contain some dangers when used in a webbased application for generation large images on the fly.

Most problems are related to ImageIOs filed based caching and not flushing buffers when an IOException in an underlying stream occurs.

First, the javax.imageio.ImageReader. It caches some data in files. It is essential to dispose the reader and the underlying ImageInputStream after use if it’s not needed anymore like so:

if(imageReader.getInput() != null && imageReader.getInput() instanceof ImageInputStream)			
  ((ImageInputStream)imageReader.getInput()).close();
imageReader.dispose();

If it isn’t closed and disposed, the temporary cache files are either deleted not at all or maybe at the next garbage collection. I was able to bring down a VM by “java.io.FileNotFoundException: (Too many open files)” several times because i didn’t close a reader in a loop. Even the classloader wasn’t able to load any new classes after the ImageReader going mad on the file handle.

The other side is the javax.imageio.ImageWriter. There is an issue mentioned in the Tomcat Wiki.

I used the ImageWriter to dynamically create large images. I directly passed the javax.servlet.ServletOutputStream to the ImageWriter. If the generation of images takes long enough, there’s a good chance that the client aborts the request and the ServletOutputStream gets flushed right when the ImageWriter is writing to it. I didn’t have the exceptions mentioned in the wiki but my VM crashed. Great. I guess it had something to do with the native org.apache.coyote.ajp.AjpAprProtocol Ajp Apr connector i use, but that’s just guessing.

I solved this problem by using a temporary file and its related outputstream which i then stream like described here. This solution is not only faster but i also can catch any exception related to an aborting client.

Also take care to dispose the write as well like so:

try {
	 imageWriter.setOutput(out);
	 imageWriter.write(null, new IIOImage(image, null, null), iwp);
	 out.flush();
 } catch(IOException e) {                        
	 imageWriter.abort();                    
	 throw e;
 } finally {
	 try {                           
		 out.close();                            
	 } catch(Exception inner) {                              
	 }
	 imageWriter.dispose();
 }

This took me several hours to figure out… I hope someone finds this post useful.

7 comments

  1. Norman wrote:

    Thanks. I have the same problem, that the jvm crashed without any hs_err-file :-(. We use also ImageIO.read() and write(). I hope your solution will work.

    Posted on February 11, 2013 at 8:37 AM | Permalink
  2. Michael wrote:

    Hi Norman,

    You’re welcome. I’m using the solution in production since the day of the post without any further problems.

    Have a nice day,
    Michael.

    Posted on February 11, 2013 at 10:07 AM | Permalink
  3. Brian Tanner wrote:

    Hi Michael. This was very useful after the fact. I was trying to do some research as to why disposing the reader stopped me from crashing through my heap limits and found this. The problem I found was in an open source library, so this issue is out there in the wild for sure.

    http://code.google.com/p/thumb.....tail?id=44

    Posted on May 19, 2013 at 9:43 PM | Permalink
  4. Michael wrote:

    Hi Brian,

    thanks you’re feedback, highly appreciate it.

    Have a nice day,
    Michael.

    Posted on May 20, 2013 at 8:23 AM | Permalink
  5. Michael wrote:

    Also, the library you’ve mentioned looks interesting.

    I’m using http://www.imageresize4j.com/index.htm on dailyfratze.de for the resizing, as my own algorithm and JAI methods where disappointing.

    For all things exif, also to get the rotation, i’m using http://drewnoakes.com/code/exif

    The combination works well for me, but hasn’t the nice fluent api of course.

    Posted on May 20, 2013 at 8:27 AM | Permalink
  6. Matija wrote:

    Hi,

    Thank you very much! Your article helped me get clues to fix a massive problem.

    Cheers,
    Matija

    Posted on August 6, 2014 at 4:47 PM | Permalink
  7. Michael wrote:

    Thanks for your feedback, you’re welcome.

    Posted on August 6, 2014 at 4:58 PM | Permalink
Post a Comment

Your email is never published. We need your name and email address only for verifying a legitimate comment. For more information, a copy of your saved data or a request to delete any data under this address, please send a short notice to michael@simons.ac from the address you used to comment on this entry.
By entering and submitting a comment, wether with or without name or email address, you'll agree that all data you have entered including your IP address will be checked and stored for a limited time by Automattic Inc., 60 29th Street #343, San Francisco, CA 94110-4929, USA. only for the purpose of avoiding spam. You can deny further storage of your data by sending an email to support@wordpress.com, with subject “Deletion of Data stored by Akismet”.
Required fields are marked *