JDK-4745222 : 1.4 REGRESSION: java.awt.Container.add is very slow in Applets
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0,1.4.1,1.4.1_01,1.4.1_02,1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_nt,windows_2000
  • CPU: x86
  • Submitted: 2002-09-11
  • Updated: 2013-11-01
  • Resolved: 2003-09-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2_04 04Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
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
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
14-06-2004

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
05-09-2003

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
04-09-2003