JDK-7041387 : Introduce new boolean system property java.awt.smartInvalidate
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 7
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS:
    generic,solaris_10,windows_xp,windows_vista,windows_7 generic,solaris_10,windows_xp,windows_vista,windows_7
  • CPU: generic,x86
  • Submitted: 2011-05-03
  • Updated: 2017-05-16
  • Resolved: 2011-05-24
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.
JDK 7
7 b143Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
The fix for 6852592 made the invalidate() method stop on the nearest validate root when invalidating a component hierarchy. Initially we relied on the common pattern used in Swing applications: when they change a layout-related information, they (or the Swing library) should call the revalidate() method, e.g.:

component.setSize(50, 50);
component.revalidate();

In this case the revalidate() method would dispatch a validate() call on the nearest validate root, thus validating the invalid part of the component hierarchy.

However, it turns out that some Swing applications rely on the old behavior of the invalidate() method and simply call:

frame.validate();

instead of the revalidate() call. The frame is usually their top-level component (such as a JFrame or a JDialog). The fix for 6852592 made this call a no-op because the frame never gets invalidated.

Comments
SUGGESTED FIX --- old/src/share/classes/java/awt/Component.java 2011-05-03 19:09:24.000000000 +0400 +++ new/src/share/classes/java/awt/Component.java 2011-05-03 19:09:24.000000000 +0400 @@ -2887,11 +2887,12 @@ /** * Invalidates this component and its ancestors. * <p> - * All the ancestors of this component up to the nearest validate root are - * marked invalid also. If there is no a validate root container for this - * component, all of its ancestors up to the root of the hierarchy are - * marked invalid as well. Marking a container <i>invalid</i> indicates - * that the container needs to be laid out. + * By default all the ancestors of the component up to the top-most + * container of the hierarchy are marked invalid. If the {@code + * java.awt.smartInvalidate} system property is set to {@code true}, then + * invalidation stops on the nearest validate root of this component. + * Marking a container <i>invalid</i> indicates that the container needs to + * be laid out. * <p> * This method is called automatically when any layout-related information * changes (e.g. setting the bounds of the component, or adding the --- old/src/share/classes/java/awt/Container.java 2011-05-03 19:09:26.000000000 +0400 +++ new/src/share/classes/java/awt/Container.java 2011-05-03 19:09:25.000000000 +0400 @@ -41,6 +41,8 @@ import java.io.PrintStream; import java.io.PrintWriter; +import java.security.AccessController; + import java.util.Arrays; import java.util.EventListener; import java.util.HashSet; @@ -60,6 +62,8 @@ import sun.java2d.pipe.Region; +import sun.security.action.GetBooleanAction; + /** * A generic Abstract Window Toolkit(AWT) container object is a component * that can contain other AWT components. @@ -1506,12 +1510,18 @@ * Layout-related changes, such as bounds of the validate root descendants, * do not affect the layout of the validate root parent. This peculiarity * enables the {@code invalidate()} method to stop invalidating the - * component hierarchy when the method encounters a validate root. - * <p> - * If a component hierarchy contains validate roots, the {@code validate()} - * method must be invoked on the validate root of a previously invalidated - * component, rather than on the top-level container (such as a {@code - * Frame} object) to restore the validity of the hierarchy later. + * component hierarchy when the method encounters a validate root. However, + * to preserve backward compatibility this new optimized behavior is + * enabled only when the {@code java.awt.smartInvalidate} system property + * value is set to {@code true}. + * <p> + * If a component hierarchy contains validate roots and the smart {@code + * invalidate()} behavior is enabled, the {@code validate()} method must be + * invoked on the validate root of a previously invalidated component to + * restore the validity of the hierarchy later. Otherwise, calling the + * {@code validate()} method on the top-level container (such as a {@code + * Frame} object) should be used to restore the validity of the component + * hierarchy. * <p> * The {@code Window} class and the {@code Applet} class are the validate * roots in AWT. Swing introduces more validate roots. @@ -1527,13 +1537,20 @@ return false; } + private static final boolean isJavaAwtSmartInvalidate; + static { + // Don't lazy-read because every app uses invalidate() + isJavaAwtSmartInvalidate = AccessController.doPrivileged( + new GetBooleanAction("java.awt.smartInvalidate")); + } + /** * Invalidates the parent of the container unless the container * is a validate root. */ @Override void invalidateParent() { - if (!isValidateRoot()) { + if (!isJavaAwtSmartInvalidate || !isValidateRoot()) { super.invalidateParent(); } } @@ -1572,9 +1589,8 @@ * automatically. Note that the ancestors of the container may be * invalidated also (see {@link Component#invalidate} for details.) * Therefore, to restore the validity of the hierarchy, the {@code - * validate()} method should be invoked on a validate root of an - * invalidated component, or on the top-most container if the hierarchy - * does not contain validate roots. + * validate()} method should be invoked on the top-most invalid + * container of the hierarchy. * <p> * Validating the container may be a quite time-consuming operation. For * performance reasons a developer may postpone the validation of the --- old/test/java/awt/Component/Revalidate/Revalidate.java 2011-05-03 19:09:27.000000000 +0400 +++ new/test/java/awt/Component/Revalidate/Revalidate.java 2011-05-03 19:09:27.000000000 +0400 @@ -26,7 +26,7 @@ @bug 7036669 @summary Test Component.revalidate() method @author ###@###.###: area=awt.component - @run main Revalidate + @run main/othervm -Djava.awt.smartInvalidate=true Revalidate */ import java.awt.*; --- old/test/java/awt/Container/ValidateRoot/InvalidateMustRespectValidateRoots.java 2011-05-03 19:09:28.000000000 +0400 +++ new/test/java/awt/Container/ValidateRoot/InvalidateMustRespectValidateRoots.java 2011-05-03 19:09:28.000000000 +0400 @@ -26,7 +26,7 @@ @bug 6852592 @summary invalidate() must stop when it encounters a validate root @author ###@###.### - @run main InvalidateMustRespectValidateRoots + @run main/othervm -Djava.awt.smartInvalidate=true InvalidateMustRespectValidateRoots */ import javax.swing.*;
03-05-2011

EVALUATION To preserve backward compatibility the new behavior of the invalidate() method should be disabled by default. I.e. by default the method should invalidate the whole component hierarchy up to the top-most container. The new behavior should only be available when specifying a boolean property: -Djava.awt.smartInvalidate=true
03-05-2011