United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-4745222 : 1.4 REGRESSION: java.awt.Container.add is very slow in Applets

Details
Type:
Bug
Submit Date:
2002-09-11
Status:
Closed
Updated Date:
2004-02-16
Project Name:
JDK
Resolved Date:
2003-09-23
Component:
client-libs
OS:
windows_nt,windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.0,1.4.1,1.4.1_01,1.4.1_02,1.4.2
Fixed Versions:
1.4.2_04 (04)

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

Sub Tasks

Description

Name: jk109818			Date: 09/10/2002


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

java version "1.4.1-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)


FULL OPERATING SYSTEM VERSION :
all Windows OS

A DESCRIPTION OF THE PROBLEM :
a call to java.awt.Container.add can be very slow (about 3
seconds or even more) in Applets!


REGRESSION.  Last worked in version 1.3.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. compile source code
2. start html-file with the appletviewer
3. click on the "two" button
  (the center panel will become blue)
4. click on the "one" button
  it tooks about 3 seconds to switch the panel
  (see output to console)

EXPECTED VERSUS ACTUAL BEHAVIOR :
switch of the panels should simply be faster

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/*
 * Java14test.java 1.0 02/09/10
 */

import java.awt.*;
import java.applet.*;
import java.awt.event.*;

public class Java14test extends Applet implements ActionListener
{
  Panel p1 = new Panel();
  Panel p2 = new Panel();
  Panel p3 = new Panel();
  Button b1 = new Button("one");
  Button b2 = new Button("two");
  
  public void init()
  {
    setLayout(new BorderLayout());
    p1.setLayout(new BorderLayout());
    p1.add(BorderLayout.WEST, b1);
    p1.add(BorderLayout.EAST, b2);
    p2.setLayout(null);
    p3.setLayout(null);
    p2.setBackground(Color.yellow);
    p3.setBackground(Color.blue);

    p1.add(BorderLayout.CENTER, p2);
    add(BorderLayout.CENTER, p1);
    b1.addActionListener(this);
    b2.addActionListener(this);
  }

  public void actionPerformed(ActionEvent ae)
  {
    Object obj = ae.getSource();
    if (obj == b1)
    {
      long time1 = System.currentTimeMillis();
      p1.removeAll();
      long time2 = System.currentTimeMillis();
      p1.add(BorderLayout.WEST, b1);
      long time3 = System.currentTimeMillis();
      p1.add(BorderLayout.EAST, b2);
      long time4 = System.currentTimeMillis();
      p1.add(BorderLayout.CENTER, p2);
      long time5 = System.currentTimeMillis();

      invalidate();
      long time6 = System.currentTimeMillis();
      p2.repaint();
      long time7 = System.currentTimeMillis();
      validate();
      long time8 = System.currentTimeMillis();

      System.out.println("<<<<< Change-Status:");
      System.out.println("removeAll: " + (time2-time1)+"ms");
      System.out.println("add button1: " + (time3-time2)+"ms");
      System.out.println("add button2: " + (time4-time3)+"ms");
      System.out.println("add Panel 1: " + (time5-time4)+"ms");
      System.out.println("showing    : " + (time8-time5)+"ms");
      System.out.println("all        : " + (time8-time1)+"ms");
    }
    else if (obj == b2)
    {
      long time1 = System.currentTimeMillis();
      p1.removeAll();
      long time2 = System.currentTimeMillis();
      p1.add(BorderLayout.WEST, b1);
      long time3 = System.currentTimeMillis();
      p1.add(BorderLayout.EAST, b2);
      long time4 = System.currentTimeMillis();
      p1.add(BorderLayout.CENTER, p3);
      long time5 = System.currentTimeMillis();

      invalidate();
      long time6 = System.currentTimeMillis();
      p3.repaint();
      long time7 = System.currentTimeMillis();
      validate();
      long time8 = System.currentTimeMillis();

      System.out.println("<<<<< Change-Status:");
      System.out.println("removeAll: " + (time2-time1)+"ms");
      System.out.println("add button1: " + (time3-time2)+"ms");
      System.out.println("add button2: " + (time4-time3)+"ms");
      System.out.println("add Panel 2: " + (time5-time4)+"ms");
      System.out.println("showing    : " + (time8-time5)+"ms");
      System.out.println("all        : " + (time8-time1)+"ms");
    }
  }
}



<html>
<applet code=Java14test.class
    height=150 width=200>
</applet>
</html>

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
use CardLayout instead of removing old panel
and adding new one

Release Regression From : 1.3.1_04
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 164280) 
======================================================================

                                    

Comments
EVALUATION

Commit to fix in Tiger (performance).  
###@###.### 2002-09-10

I verified that this problem may be partly caused by the fix for 4530093. It is
a painting problem. The 5seconds that it throttles the CPU to 100%
is spent repeatedly in PaintUpdateRgn. There are six other bugs that
are related to the same problem : We need to fix this for tiger.

4873526
4745222
4884034
4878438
4673954
4827244
4770534
4895361

###@###.### 2003-09-03

Looks like we are not validating the region for WM_PAINT messages that are
received after the window is created and before the callbacks are enabled. This
leads to a window where Windows repeatedly returns WM_PAINT and gets into a tight loop, causing CPU utilization to go up to 100% and starve the main thread
which needs to complete initialization. The fix is to simply vaidate the regions
(before callbacks are enabled) and then to invalidate prior to Enabling the callbacks.

###@###.### 2003-09-04
                                     
2003-09-04
SUGGESTED FIX

------- awt_Component.cpp -------
*** /tmp/sccs.95aOhe    Thu Sep  4 17:01:50 2003
--- awt_Component.cpp   Wed Sep  3 21:08:12 2003
***************
*** 2134,2139 ****
--- 2134,2146 ----
  {
      // Fix 4530093: Don't Validate if can't actually paint
      if (m_peerObject == NULL || !m_callbacksEnabled) {
+         
+         // Fix 4745222: If we dont ValidateRgn,  windows will keep sending
+         // WM_PAINT messages until we do. This causes java to go into 
+         // a tight loop that increases CPU to 100% and starves main
+         // thread which needs to complete initialization, but cant.
+         ::ValidateRgn(GetHWnd(), NULL);
+        
          return;
      }
  
***************
*** 6112,6117 ****
--- 6119,6127 ----
       */
      p->EnableCallbacks(TRUE);
  
+     // Fix 4745222: we need to invalidate region since we validated it before initialization.
+     ::InvalidateRgn(p->GetHWnd(),NULL,FALSE);
+ 
      // Fix 4530093: WM_PAINT after EnableCallbacks
      ::UpdateWindow(p->GetHWnd());
  

I verified that 4530093 is still fixed.

###@###.### 2003-09-04

I tested all the duplicate bugs with the excpetion of  They all are now
fixed. 4673954, is not testable because the testcase is no longer working 
with tiger.

###@###.### 2003-09-05

This fix could be easily back ported to Mantis.

###@###.### 2003-09-05
                                     
2003-09-05
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
1.4.2_04
generic
tiger

FIXED IN:
1.4.2_04
tiger

INTEGRATED IN:
1.4.2_04
tiger
tiger-b21

VERIFIED IN:
1.4.2_04


                                     
2004-06-14



Hardware and Software, Engineered to Work Together