United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4827358 Use of finalization in JPEGImageReader/Writer degrades performance
JDK-4827358 : Use of finalization in JPEGImageReader/Writer degrades performance

Details
Type:
Bug
Submit Date:
2003-03-05
Status:
Resolved
Updated Date:
2003-09-15
Project Name:
JDK
Resolved Date:
2003-09-15
Component:
client-libs
OS:
windows_xp,windows_2000
Sub-Component:
javax.imageio
CPU:
x86
Priority:
P3
Resolution:
Fixed
Affected Versions:
1.4.1,1.4.2
Fixed Versions:
5.0 (tiger)

Related Reports
Backport:
Backport:
Duplicate:
Relates:
Relates:

Sub Tasks

Description

Name: nt126004			Date: 03/04/2003


FULL PRODUCT VERSION :
java version "1.4.1_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_02-b06)
Java HotSpot(TM) Client VM (build 1.4.1_02-b06, mixed mode)

FULL OS VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Memory allocation doesn't wait for finalization to catch up.
Almost all programs run more than 1 thread which is creating objects, meanwhile only one thread is finalizing them, eventually OutOfMemoryErrors are thrown at almost random places throughout the code, making the code extremely fragile.

Changing VM paramters to alter Garbage Collector behaviour makes no difference, the code fails no matter what the parameters.  Increasing the max heap size only delays the problem.

This problem only started to be really bad when JDK 1.4 came out.  The cause of this is that many of the new imageio and nio classes have finalize methods causing them to require finalizing before they can get garbage collected.  Despite the fact the the Finalizer thread runs at a higher priority, these new classes still block for a short amount of time hence finalization is getting blocked.

The more threads allocating objects requiring finalization the worse the problem gets.

Some of the imageio classes are using several meg of memory, which could easily be garbage collected before finalization was run.  Simply have the image classes hold a sub object with a finalize method and a handle such that it can call dispose instead of the image classes directly having the finalize method and hence having to wait for the Finalizer thread before they release several megs of memory.  The problem still needs to get fixed, but this would atleast give programs using the imageio a chance to continue without the bug getting fixed.

Related Bugs: 4811982, 4640743, 4239841

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
run code and wait for the OutOfMemoryError

EXPECTED VERSUS ACTUAL BEHAVIOR :
With each of the 2 new threads only using 1 object each, I would expect this code to run forever without a problem.  The code only needs about 2MB to run, yet it throws OutOfMemoryErrors no matter how much memory the VM allocates to it.
Thread dies due to OutOfMemoryError.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class TestObject {
  private byte[] bytes;
  private static int createdCount;
  private static int finalizedCount;

  public TestObject() {
    bytes = new byte[1000000];
    try {
      Thread.sleep(500);
    }
    catch (InterruptedException ex) {
    }
    System.out.println("Created " + ++createdCount);
  }

  public void finalize() {
    try {
      Thread.sleep(500);
    }
    catch (InterruptedException ex) {
    }
    System.out.println("Finalized " + ++finalizedCount);
  }
}

class TestThread extends Thread {
  public void run() {
    while (true) {
      TestObject testObject = new TestObject();
      // do something with object
      testObject = null; // allow it to get garbage collected
      // continue with something else
    }
  }
}

public class Test {
  public static void main(String[] args) {
    new TestThread().start();
    new TestThread().start();
  }
}
---------- END SOURCE ----------
(Review ID: 182033) 
======================================================================

                                    

Comments
EVALUATION

We can't build a garbage collector for Java that would "wait for finalization
to catch up" before throwing an OutOfMemoryError since finalize() methods can
themselves allocate memory, and we can't prevent that without making some
fairly extreme changes to the language itself.

The invocation of an object's finalize() method can be delayed an arbitrarily
long time from the moment that the object is detected to be finalizable by the
GC.  Objects with finalize() methods also have longer lifetimes since they have
to be kept around long enough for the GC to discover that they're finalizable,
finalize them, and then finally reclaim them.  Finalization is hence, at best,
a back-stop mechanism for deallocating external resources such as I/O or image
buffers.

Owing to the performance overhead of finalization the NIO channel classes were
revised so as not to use it in 1.4.2 (4777499).  I'm forwarding this bug to the
Image I/O team for further evaluation.

-- ###@###.### 2003/3/6

We should remove the finalize() methods and instead make use of the Java 2D
Disposer mechanism for disposing native resources.  There are some explicit
System.gc() calls in the JPEG ImageReader/Writer plugins (see bug 4867874)
that can be removed once the Disposer is used.  (These two bugs should be
handled simultaneously...)
###@###.### 2003-05-23
                                     
2003-05-23
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b20


                                     
2004-06-14



Hardware and Software, Engineered to Work Together