-
Bug
-
Resolution: Fixed
-
P3
-
1.2.2, 1.4.2
-
tiger
-
x86, sparc
-
linux, solaris_8
Name: rmT116609 Date: 08/08/2003
FULL PRODUCT VERSION :
On Linux and Solaris 8, we've tried:
java version "1.4.2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-b28)
Java HotSpot(TM) Client VM (build 1.4.2-b28, mixed mode)
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
On Solaris 2.6 and 8, we've tried:
java version "1.2.2"
Solaris VM (build Solaris_JDK_1.2.2_05, native threads, sunwjit)
java version "1.3.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_01)
Java HotSpot(TM) Client VM (build 1.3.1_01, mixed mode)
FULL OS VERSION :
Linux wsvapp1.prod.netsol.com 2.4.20 #8 SMP Thu Feb 20 11:55:41 EST 2003 i686 i686 i386 GNU/Linux
SunOS new-engfs 5.6 Generic_105181-30 sun4u sparc SUNW,Ultra-4
SunOS dapp2 5.8 Generic_108528-13 sun4u sparc SUNW,Ultra-80
A DESCRIPTION OF THE PROBLEM :
We have a website builder application which accepts JPEG images from
customers posted through web forms. One customer has been submitting
an image which causes our application server instances (Weblogic) to
appear to "hang". Closer inspection through a series of thread dumps
and verbose GC output shows that the JPEGImageDecoder (sun.awt.image.codec)
gets into what appears to be an infinite loop, continuously throwing a
TruncatedFileException, which in the process of instantiating does a
getData on the buffered image. CPU metrics on the servers also show
that one CPU is fully utilized for each thread in this state. This
ultimately leads to an OutOfMemory error as doing the getData causes
the creation of many DataBufferInt objects for each Raster. Only this
one image, which is apparently from an EXIF image generated from a
digital camera, causes the problem. Other EXIF images from what seem to
be the same digital camera are ok, as are other normal JFIF images.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I can provide the JPEG image via email. Please contact me at
###@###.###.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
This test program should exit gracefully without any errors when a normal JPEG image is passed to it.
ACTUAL -
With verbosegc turned on:
For JDK 1.2.2_05:
/opt/jdk/1.2.2_05/bin/java -verbosegc -classpath . JpegTest corrupt.jpg
Output:
Corrupt JPEG data: 1 extraneous bytes before marker 0xeb
GC[1] in 15 ms: (8Mb, 24% free) -> (13Mb, 54% free)
GC[1] in 7 ms: (13Mb, 12% free) -> (22Mb, 47% free)
GC[1] in 8 ms: (22Mb, 14% free) -> (24Mb, 22% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 9 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 7 ms: (24Mb, 6% free) -> (24Mb, 6% free)
GC[1] in 6 ms: (24Mb, 6% free) -> (24Mb, 6% free)
.... etc....
For JDK 1.3.1_01:
Command executed (with slightly modified java.awt.image.DataBufferInt
in the current working directory, see test case source code):
/opt/jdk/1.3.1_01/bin/java -Xbootclasspath/p:. -verbosegc -classpath . JpegTest corrupt.jpg
Output:
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 233K->225K(3520K), 0.0102671 secs]
[GC 2273K->2185K(5400K), 0.0349507 secs]
Corrupt JPEG data: 1 extraneous bytes before marker 0xeb
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 4143K->4073K(5704K), 0.0431293 secs]
[Full GC 4073K->4073K(5704K), 0.0295958 secs]
[Full GC 4073K->4073K(5704K), 0.0264856 secs]
[Full GC 4073K->4065K(5704K), 0.0469216 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 5944K->5940K(9464K), 0.0285838 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 7819K->7816K(11944K), 0.0322151 secs]
[Full GC 7816K->7816K(15144K), 0.0507099 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 9695K->9691K(15144K), 0.0224634 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 11570K->11567K(15144K), 0.0218378 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 13446K->13442K(17024K), 0.0225634 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 15321K->15318K(25224K), 0.0373452 secs]
[Full GC 15318K->15318K(28736K), 0.0848818 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 17197K->17193K(28736K), 0.0235117 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 19072K->19068K(28736K), 0.0224093 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 20948K->20944K(28736K), 0.0232652 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 22823K->22819K(28736K), 0.0234453 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 24699K->24695K(28736K), 0.0236502 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 26574K->26570K(30616K), 0.0238701 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 28449K->28446K(49664K), 0.0332514 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 30325K->30321K(49664K), 0.0507672 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 34080K->34072K(49664K), 0.0477233 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 37831K->37823K(49664K), 0.0476455 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 41581K->41574K(49664K), 0.0445367 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 45332K->45325K(51544K), 0.0473435 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 49083K->49076K(65280K), 0.0472320 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 50955K->50951K(65280K), 0.0696386 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[GC 56589K->56578K(65280K), 0.0675687 secs]
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
DataBufferInt.<init>: About to init an int[] of size: 480000
[Full GC 62215K->62204K(65280K), 0.0469784 secs]
[Full GC 62204K->62204K(65280K), 0.2728592 secs]
[Full GC 62204K->62204K(65280K), 0.0366729 secs]
[Full GC 62204K->62204K(65280K), 0.0319090 secs]
java.lang.OutOfMemoryError
<<no stack trace available>>
For JDK 1.4.1_01:
/opt/jdk/1.4.1_01/bin/java -verbosegc -classpath . JpegTest corrupt.jpg
[GC 407K->295K(3520K), 0.0171082 secs]
[GC 2343K->2253K(5400K), 0.0285024 secs]
[Full GC 2253K->2253K(5400K), 0.0376267 secs]
Corrupt JPEG data: 1 extraneous bytes before marker 0xeb
[GC 2474K->2376K(5872K), 0.0069639 secs]
[GC 4254K->4251K(7752K), 0.0208303 secs]
[Full GC 4251K->4251K(7752K), 0.0358919 secs]
[GC 8009K->8002K(11080K), 0.0194844 secs]
[Full GC 8002K->8002K(11080K), 0.0302692 secs]
[GC 13638K->13629K(17336K), 0.0190322 secs]
[Full GC 13629K->13596K(17336K), 0.0913812 secs]
[GC 22990K->22974K(27360K), 0.0198069 secs]
[Full GC 22974K->22974K(27360K), 0.0350351 secs]
[GC 41761K->41728K(46792K), 0.0403221 secs]
[Full GC 41728K->41728K(46792K), 0.0405850 secs]
[Full GC 62394K->62359K(65344K), 0.0502778 secs]
[Full GC 62359K->62359K(65344K), 0.3294525 secs]
[Full GC 62359K->62359K(65344K), 0.0400253 secs]
[Full GC 62359K->62359K(65344K), 0.0328533 secs]
[Full GC 62359K->62359K(65344K), 0.0329569 secs]
[Full GC 62359K->62359K(65344K), 0.0330539 secs]
[Full GC 62359K->62359K(65344K), 0.0327767 secs]
[Full GC 62359K->62359K(65344K), 0.0328069 secs]
[Full GC 62360K->62360K(65344K), 0.0326779 secs]
[Full GC 62360K->62360K(65344K), 0.0328628 secs]
[Full GC 62360K->62360K(65344K), 0.0326780 secs]
[Full GC 62360K->62360K(65344K), 0.0330385 secs]
[Full GC 62360K->62360K(65344K), 0.0325427 secs]
... etc...
ERROR MESSAGES/STACK TRACES THAT OCCUR :
See actual result data.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
This simple test class can reproduce the problem under any JDK version
1.2.2, 1.3.1, or 1.4.1, assuming that you pass in the proper corrupted
JPEG image:
import com.sun.image.codec.jpeg.ImageFormatException;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import com.sun.image.codec.jpeg.TruncatedFileException;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
public class JpegTest
{
public static void main(String[] args)
{
ByteArrayInputStream is = null;
try
{
File sourceFile = new File(args[0]);
byte[] data = new byte[(int)sourceFile.length()];
RandomAccessFile f = new RandomAccessFile(sourceFile, "r");
f.readFully(data);
f.close();
is = new ByteArrayInputStream(data);
JPEGImageDecoder dec = JPEGCodec.createJPEGDecoder(is);
BufferedImage bufferedImage = dec.decodeAsBufferedImage();
}
catch(IOException io)
{
io.printStackTrace();
}
catch( Throwable t)
{
t.printStackTrace();
}
finally
{
if(is != null)
{
try
{
is.close();
}
catch(IOException io)
{}
}
}
}
}
For diagnostics purposes only, I also slightly modified
java.awt.image.DataBufferInt so that the constructor dumped a
debug message as follows:
/**
* Constructs an integer-based <CODE>DataBuffer</CODE> with a single bank
* and the specified size.
*
* @param size The size of the <CODE>DataBuffer</CODE>.
*/
public DataBufferInt(int size) {
super(TYPE_INT,size);
System.out.println("DataBufferInt.<init>: About to init an int[] of size: " + size);
data = new int[size];
bankdata = new int[1][];
bankdata[0] = data;
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Currently, we have locked out the customer causing this problem.
(Incident Review ID: 193662)
======================================================================
- relates to
-
JDK-4977007 JPEG Image Decoding questionable as a result of fixes for bugs 4836529, 4903659
-
- Resolved
-