JDK-6236802 : Scaling special Jpeg image tops CPU to 100%
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 5.0
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: x86
  • Submitted: 2005-03-07
  • Updated: 2015-11-03
Related Reports
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
Java HotSpot(TM) Client VM (build 1.5.0_01-b08, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Fedora Core 1,2 & 3

A DESCRIPTION OF THE PROBLEM :
Reading and rescalling the image found at the following URL hangs the code, and tops the CPU at 100%.
Even launching the rescale in a separate thread and stoping the thread  doesn't help cooling the CPU that stays @ 100%.

As I can't upload files, on this form, the image can be found here :
http://test.windsofcabarete.com:8080/windsOfCabarete/getForumPicture?code=1107139181101

The image seems ok, and can be open in any graphics programm. If I open it in Gimp and save it again, the problem is gone with the new image.

I run a website where users can post messages with an image.
The image is then rescalled in several situation.
Since this image has been posted, the server was rebooted every hour by a watchdog because the CPU was 100%, and the server becomes slowly totaly irresponsive.

I guess this is linked to the coding of the image, but ImageIO.read can read perfectly well the image. The bug apears when you apply a transformation to the image (see test source code bellow).

  To avoid the problem, I separated the rescaling of the image in a FutureTask, and shut it down after 30 sec. if it hasn't been completed.
But even shutting down the computation doesn't resolve the problem. The task should have been gone, but the CPU remains @ 100%.
I had a similar problem

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Download the image at the following URL :
http://test.windsofcabarete.com:8080/windsOfCabarete/getForumPicture?code=1107139181101

Rename it to buggyGetForumPicture.jpg

Run the attached source code in the same directory.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Just the image being resized (no output though in the attached test).

This works with any other image I've tested this program with so far.
ACTUAL -
You'll see the tasks hanging, and after 3 attempts, you'll see some

java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: Java heap space
        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:215)
        at java.util.concurrent.FutureTask.get(FutureTask.java:85)
        at TestBuggyImage.getResizedPhoto(TestBuggyImage.java:46)
        at TestBuggyImage.main(TestBuggyImage.java:32)
Caused by: java.lang.OutOfMemoryError: Java heap space

Runing a similar code in a Servelet (I use tomcat 5.5.7) will have the CPU top 100% forever, and the server will slowly become totaly irresponsive (takes about 1 hour).

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * $LastChangedBy: sylvain $
 * $LastChangedDate: 2005-01-30 22:46:59 -0400 (Sun, 30 Jan 2005) $
 * $LastChangedRevision: 1297 $
 */

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.imageio.ImageIO;

/**
 * @author sylvain
 */
public class TestBuggyImage  {
    static public void main (String[] args){
        for(int i=0; i<10 ; i++){
            System.out.println("Going for # "+i);
            try{
                getResizedPhoto();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        
        System.out.println("Done.");
        
    }

    static public byte[] getResizedPhoto() throws InterruptedException, ExecutionException, TimeoutException {
        ExecutorService es = Executors.newSingleThreadExecutor();
        Future<byte[]> future = es.submit( new ResizeRunner() );
        
        byte[] bytes = future.get(30, TimeUnit.SECONDS);
        future.cancel( true );
        
        es.shutdownNow ();
        
		return bytes;
    }
    
    static private class ResizeRunner implements Callable<byte[]>{
        public byte[] call() throws IOException{
            System.setProperty("java.awt.headless", "true");
            
            int size = 300;
            
            int width = size;
            int height = size;
            
            Image rawImage = ImageIO.read( new File("buggyGetForumPicture.jpg") );
            
            int rawImageWidth = -1;
            int rawImageHeight = -1;
            try{
                rawImageWidth = rawImage.getWidth(null);
                rawImageHeight = rawImage.getHeight(null);
            }catch(RuntimeException re){
                re.printStackTrace();
                throw re;
            }

            double maxScale = Math.min(width / (double) rawImageWidth, height / (double) rawImageHeight);
            
            BufferedImage image = new BufferedImage((int) (rawImageWidth * maxScale), (int) (rawImageHeight * maxScale), BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = image.createGraphics();
            g2.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING, java.awt.RenderingHints.VALUE_ANTIALIAS_ON);

            // The bug doesn't appear if the AffineTransform isn't applied.
            AffineTransform scaleTransform = AffineTransform.getScaleInstance(maxScale, maxScale);
            g2.setTransform(scaleTransform);
    
            System.out.println("Before drawImage.");
            
            g2.drawImage(rawImage, null, null);
            
            System.out.println("Image drawn.");
    
            g2.dispose();
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "jpeg", baos);
            
            return baos.toByteArray();
        }
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Prevent users from posting pictures ... which is impossible in my case :-(
###@###.### 2005-03-07 12:00:33 GMT

Comments
Please re-open if - if fix is in progress or on the plan to fix soon - if this is a P3 (file as P3, not P4)
18-03-2014

EVALUATION The most part of the execution time is consumed by scale transform operation on the TYPE_3BYTE_BGR buffered image. The problem related to performance of the scale transforms on such image types was addressed by fix for CR 5073407. The problem described in this CR is not reproducible starting 5.0_02b02 and 6.0b06.
03-10-2005

EVALUATION Most likely a duplicate of 4705399 (scaling is slow for JPEG images with non-standard color spaces). ###@###.### 2005-05-05 18:40:56 GMT
05-05-2005