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
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.
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.
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
Hi Brian,
thanks you’re feedback, highly appreciate it.
Have a nice day,
Michael.
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.
Hi,
Thank you very much! Your article helped me get clues to fix a massive problem.
Cheers,
Matija
Thanks for your feedback, you’re welcome.
Post a Comment