Crash in Java 1.6.0_13 ImageIO PNG decoder (and possibly later versions) loading large interlaced PNGs with low memory
Using Java 1.6.0_13 -server -Xmx1100M what do you get if you run this code?
import java.lang.ref.SoftReference;
import java.io.File;
import javax.imageio.ImageIO;
public class Crash {
public static void main (char[] args) {
File f = new File("path-to-any-24-megapixel-RGB-PNG-goes-here");
SoftReference a = new SoftReference(ImageIO.read(f));
SoftReference b = new SoftReference(ImageIO.read(f));
SoftReference c = new SoftReference(ImageIO.read(f));
SoftReference d = new SoftReference(ImageIO.read(f));
SoftReference e = new SoftReference(ImageIO.read(f));
System.out.println("" + (a.get() == null) + (b.get() == null)
+ (c.get() == null) + (d.get() == null) + (e.get() == null));
}
}
It should be easy for any of you with a digital camera to adapt this --
just change the filename string to point to a 24-megapixel image you have
laying around. Failing that, there's one linked at the bottom left of
http://aerialphotographysandiego.com/samples-aerial-photography-san-diego.html
The above will work fine with jpegs and noninterlaced pngs, reporting
falsefalsefalsefalsefalse if you have more than a few hundred megs of mem
and the -server VM. Convert the image to an interlaced png and point the
above at the png, though, and it seems to behave as if System.exit was
called, at least on my system, which is clearly incorrect behavior. (I
tested it with the file from that link, converted to interlaced png with
Photoshop CS2, in case that somehow makes a difference -- with a decoder
bug, who knows? With the png created as described, it crashes with five
copies loaded, but not with four.)
Curiously, this change seems to prevent it:
import java.lang.ref.SoftReference;
import java.io.File;
import javax.imageio.ImageIO;
public class Crash {
public static void main (char[] args) {
File f = new File("path-to-a-24-megapixel-RGB-PNG-goes-here");
SoftReference a = new SoftReference(ImageIO.read(f));
System.gc();
SoftReference b = new SoftReference(ImageIO.read(f));
System.gc();
SoftReference c = new SoftReference(ImageIO.read(f));
System.gc();
SoftReference d = new SoftReference(ImageIO.read(f));
System.gc();
SoftReference e = new SoftReference(ImageIO.read(f));
System.out.println("" + (a.get() == null) + (b.get() == null)
+ (c.get() == null) + (d.get() == null) + (e.get() == null));
}
}
That's clearly buggy, because System.gc() added or removed is not supposed
to alter program semantics, only maybe performance; PLUS if it was running
out of memory some SoftReferences should have been cleared to make more
room without anything else in the way of consequences; PLUS if it somehow
ran out of memory anyway it should have thrown an OOME rather than
pretended the code called System.exit.
As near as I can tell from this, the ImageIO png decoder in Java 1.6.0_13
contains a crash-inducing bug that requires the png it's decoding to be
interlaced *and* requires heap space to be running low to trigger it.
I'm curious to know what other Java versions reproduce this buggy behavior.
If it's present in 1.6.0_13 but absent in a later version, then obviously
I'd especially like to know that.
But I don't feel like going to a huge effort downloading a hundred megs of
later-Java-version, installing it, rebooting, fixing everything I'd need to
fix to make stuff use the later version, fixing broken links because the
binary pathname changed, and so forth, only to find out that the bug's
still there in the current version. :) So I'd like confirmation that it's
gone in some later version before I spend an hour or two of my life on such
a task.