6919629: Nimbus L&F Nimbus.Overrides option leaks significant amounts of memory
Reviewed-by: rupashka
--- a/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java Fri Apr 30 11:03:38 2010 -0700
+++ b/jdk/src/share/classes/javax/swing/plaf/nimbus/NimbusStyle.java Thu May 06 12:57:30 2010 +0400
@@ -38,6 +38,7 @@
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -193,7 +194,7 @@
* UIDefaults which overrides (or supplements) those defaults found in
* UIManager.
*/
- private JComponent component;
+ private WeakReference<JComponent> component;
/**
* Create a new NimbusStyle. Only the prefix must be supplied. At the
@@ -209,7 +210,9 @@
* should be null otherwise.
*/
NimbusStyle(String prefix, JComponent c) {
- this.component = c;
+ if (c != null) {
+ this.component = new WeakReference<JComponent>(c);
+ }
this.prefix = prefix;
this.painter = new SynthPainterImpl(this);
}
@@ -251,9 +254,11 @@
// value is an instance of UIDefaults, then these defaults are used
// in place of, or in addition to, the defaults in UIManager.
if (component != null) {
- Object o = component.getClientProperty("Nimbus.Overrides");
+ // We know component.get() is non-null here, as if the component
+ // were GC'ed, we wouldn't be processing its style.
+ Object o = component.get().getClientProperty("Nimbus.Overrides");
if (o instanceof UIDefaults) {
- Object i = component.getClientProperty(
+ Object i = component.get().getClientProperty(
"Nimbus.Overrides.InheritDefaults");
boolean inherit = i instanceof Boolean ? (Boolean)i : true;
UIDefaults d = (UIDefaults)o;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/nimbus/Test6919629.java Thu May 06 12:57:30 2010 +0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ @bug 6919629
+ @summary Tests that components with Nimbus.Overrides are GC'ed properly
+ @author Peter Zhelezniakov
+ @run main Test6919629
+*/
+
+import java.awt.Color;
+import java.lang.ref.WeakReference;
+import javax.swing.*;
+import javax.swing.plaf.nimbus.NimbusLookAndFeel;
+
+public class Test6919629
+{
+ JFrame f;
+ WeakReference<JLabel> ref;
+
+ public static void main(String[] args) throws Exception {
+ UIManager.setLookAndFeel(new NimbusLookAndFeel());
+ Test6919629 t = new Test6919629();
+ t.test();
+ System.gc();
+ t.check();
+ }
+
+ void test() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ UIDefaults d = new UIDefaults();
+ d.put("Label.textForeground", Color.MAGENTA);
+
+ JLabel l = new JLabel();
+ ref = new WeakReference<JLabel>(l);
+ l.putClientProperty("Nimbus.Overrides", d);
+
+ f = new JFrame();
+ f.getContentPane().add(l);
+ f.pack();
+ f.setVisible(true);
+ }
+ });
+ Thread.sleep(2000);
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ public void run() {
+ f.getContentPane().removeAll();
+ f.setVisible(false);
+ f.dispose();
+ }
+ });
+ Thread.sleep(2000);
+ }
+
+ void check() {
+ if (ref.get() != null) {
+ throw new RuntimeException("Failed: an unused component wasn't collected");
+ }
+ }
+}