From 5b04b875ea7823ef0ac55e67143088066c84ab3c Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Thu, 22 Oct 2009 18:42:18 +0400 Subject: [PATCH] 6795356: Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc Reviewed-by: hawtin --- jdk/src/share/classes/javax/swing/JTable.java | 3 +- .../javax/swing/plaf/metal/OceanTheme.java | 3 +- .../classes/sun/swing/SwingLazyValue.java | 16 ++- .../6795356/SwingLazyValueTest.java | 44 ++++++++ .../swing/UIDefaults/6795356/TableTest.java | 52 +++++++++ .../swing/UIDefaults/6795356/bug6795356.java | 100 ++++++++++++++++++ 6 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 jdk/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java create mode 100644 jdk/test/javax/swing/UIDefaults/6795356/TableTest.java create mode 100644 jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index 521f17ab8a5..28b38ce0c6a 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -57,6 +57,7 @@ import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2.Section; import static sun.swing.SwingUtilities2.Section.*; import sun.swing.PrintingStatus; +import sun.swing.SwingLazyValue; /** * The JTable is used to display and edit regular two-dimensional tables @@ -5316,7 +5317,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable } private void setLazyValue(Hashtable h, Class c, String s) { - h.put(c, new UIDefaults.ProxyLazyValue(s)); + h.put(c, new SwingLazyValue(s)); } private void setLazyRenderer(Class c, String s) { diff --git a/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java b/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java index 2aa299fe5cc..2e1a8b2b4bf 100644 --- a/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java +++ b/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java @@ -32,6 +32,7 @@ import javax.swing.*; import javax.swing.plaf.*; import sun.swing.SwingUtilities2; import sun.swing.PrintColorUIResource; +import sun.swing.SwingLazyValue; /** * The default theme for the {@code MetalLookAndFeel}. @@ -128,7 +129,7 @@ public class OceanTheme extends DefaultMetalTheme { * @throws NullPointerException if {@code table} is {@code null} */ public void addCustomEntriesToTable(UIDefaults table) { - Object focusBorder = new UIDefaults.ProxyLazyValue( + Object focusBorder = new SwingLazyValue( "javax.swing.plaf.BorderUIResource$LineBorderUIResource", new Object[] {getPrimary1()}); // .30 0 DDE8F3 white secondary2 diff --git a/jdk/src/share/classes/sun/swing/SwingLazyValue.java b/jdk/src/share/classes/sun/swing/SwingLazyValue.java index f5587282abb..02236ddff73 100644 --- a/jdk/src/share/classes/sun/swing/SwingLazyValue.java +++ b/jdk/src/share/classes/sun/swing/SwingLazyValue.java @@ -26,6 +26,9 @@ package sun.swing; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.AccessibleObject; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.swing.UIDefaults; /** @@ -65,13 +68,15 @@ public class SwingLazyValue implements UIDefaults.LazyValue { if (methodName != null) { Class[] types = getClassArray(args); Method m = c.getMethod(methodName, types); + makeAccessible(m); return m.invoke(c, args); } else { Class[] types = getClassArray(args); Constructor constructor = c.getConstructor(types); + makeAccessible(constructor); return constructor.newInstance(args); } - } catch(Exception e) { + } catch (Exception e) { // Ideally we would throw an exception, unfortunately // often times there are errors as an initial look and // feel is loaded before one can be switched. Perhaps a @@ -81,6 +86,15 @@ public class SwingLazyValue implements UIDefaults.LazyValue { return null; } + private void makeAccessible(final AccessibleObject object) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + object.setAccessible(true); + return null; + } + }); + } + private Class[] getClassArray(Object[] args) { Class[] types = null; if (args!=null) { diff --git a/jdk/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java b/jdk/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java new file mode 100644 index 00000000000..4211e53cd8e --- /dev/null +++ b/jdk/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java @@ -0,0 +1,44 @@ +/* + * 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 6795356 + * @summary Checks that SwingLazyValue class correclty works + * @author Alexander Potochkin + * @run main SwingLazyValueTest + */ + +import sun.swing.SwingLazyValue; + +import javax.swing.*; + +public class SwingLazyValueTest { + + public static void main(String[] args) throws Exception { + if(new SwingLazyValue("javax.swing.JTable$DoubleRenderer"). + createValue(null) == null) { + throw new RuntimeException("SwingLazyValue doesn't work"); + } + } +} diff --git a/jdk/test/javax/swing/UIDefaults/6795356/TableTest.java b/jdk/test/javax/swing/UIDefaults/6795356/TableTest.java new file mode 100644 index 00000000000..6002f816979 --- /dev/null +++ b/jdk/test/javax/swing/UIDefaults/6795356/TableTest.java @@ -0,0 +1,52 @@ +/* + * 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 6795356 + * @summary Checks that SwingLazyValue class correclty works + * @author Alexander Potochkin + * @run main/othervm TableTest + */ + +import sun.applet.AppletSecurity; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import java.awt.*; + +public class TableTest { + + public static void main(String[] args) throws Exception { + + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + System.setSecurityManager(new AppletSecurity()); + + JTable table = new JTable(); + TableCellEditor de = table.getDefaultEditor(Double.class); + if (de == null) { + throw new RuntimeException("Table default editor is null"); + } + } +} + diff --git a/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java b/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java new file mode 100644 index 00000000000..89e33f1cf82 --- /dev/null +++ b/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java @@ -0,0 +1,100 @@ +/* + * 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 6795356 + * @summary Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc + * @author Alexander Potochkin + * @run main bug6795356 + */ + +import java.lang.ref.WeakReference; +import java.security.ProtectionDomain; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.AccessControlContext; +import java.util.LinkedList; +import java.util.List; +import javax.swing.*; + +public class bug6795356 { + volatile static WeakReference weakRef; + + public static void main(String[] args) throws Exception { + + ProtectionDomain domain = new ProtectionDomain(null, null); + + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + + // this initialize ProxyLazyValues + UIManager.getLookAndFeel(); + + return null; + } + }, new AccessControlContext(new ProtectionDomain[]{domain})); + + weakRef = new WeakReference(domain); + domain = null; + + // Generate OutOfMemory and check the weak ref + generateOOME(); + + if (weakRef.get() != null) { + throw new RuntimeException("Memory leak found!"); + } + System.out.println("Test passed"); + } + + static void generateOOME() { + List bigLeak = new LinkedList(); + boolean oome = false; + System.out.print("Filling the heap"); + try { + for(int i = 0; true ; i++) { + // Now, use up all RAM + bigLeak.add(new byte[1024 * 1024]); + System.out.print("."); + + // Give the GC a change at that weakref + if (i % 10 == 0) { + System.gc(); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } catch (OutOfMemoryError e) { + bigLeak = null; + oome = true; + } + System.out.println(""); + if (!oome) { + throw new RuntimeException("Problem with test case - never got OOME"); + } + System.out.println("Got OOME"); + } +}