OpenJDK / jdk / jdk10
changeset 26033:3f7c9aad7cc0
8017284: Aqua LaF: memory leak when HTML is used for JTabbedPane tab titles
Reviewed-by: serb, pchelko
author | alexsch |
---|---|
date | Fri, 08 Aug 2014 16:19:36 +0400 |
parents | a60a06edaf4e |
children | a5efd96d0482 |
files | jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java jdk/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java jdk/test/javax/swing/JTabbedPane/8017284/bug8017284.java |
diffstat | 3 files changed, 109 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Fri Aug 08 16:13:15 2014 +0400 +++ b/jdk/src/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java Fri Aug 08 16:19:36 2014 +0400 @@ -3307,7 +3307,7 @@ pane.repaint(); } else if (name == "indexForTitle") { calculatedBaseline = false; - updateHtmlViews((Integer) e.getNewValue()); + updateHtmlViews((Integer) e.getNewValue(), false); } else if (name == "tabLayoutPolicy") { AquaTabbedPaneCopyFromBasicUI.this.uninstallUI(pane); AquaTabbedPaneCopyFromBasicUI.this.installUI(pane); @@ -3345,7 +3345,7 @@ calculatedBaseline = false; } else if (name == "indexForNullComponent") { isRunsDirty = true; - updateHtmlViews((Integer) e.getNewValue()); + updateHtmlViews((Integer) e.getNewValue(), true); } else if (name == "font") { calculatedBaseline = false; } @@ -3464,10 +3464,10 @@ return; } isRunsDirty = true; - updateHtmlViews(tp.indexOfComponent(child)); + updateHtmlViews(tp.indexOfComponent(child), true); } - private void updateHtmlViews(int index) { + private void updateHtmlViews(int index, boolean inserted) { final String title = tabPane.getTitleAt(index); final boolean isHTML = BasicHTML.isHTMLString(title); if (isHTML) { @@ -3475,16 +3475,24 @@ htmlViews = createHTMLVector(); } else { // Vector already exists final View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.insertElementAt(v, index); + setHtmlView(v, inserted, index); } } else { // Not HTML if (htmlViews != null) { // Add placeholder - htmlViews.insertElementAt(null, index); + setHtmlView(null, inserted, index); } // else nada! } updateMnemonics(); } + private void setHtmlView(View v, boolean inserted, int index) { + if (inserted || index >= htmlViews.size()) { + htmlViews.insertElementAt(v, index); + } else { + htmlViews.setElementAt(v, index); + } + } + public void componentRemoved(final ContainerEvent e) { final JTabbedPane tp = (JTabbedPane)e.getContainer(); final Component child = e.getChild();
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Fri Aug 08 16:13:15 2014 +0400 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java Fri Aug 08 16:19:36 2014 +0400 @@ -3540,12 +3540,7 @@ else if (name =="indexForTitle") { calculatedBaseline = false; Integer index = (Integer) e.getNewValue(); - // remove the current index - // to let updateHtmlViews() insert the correct one - if (htmlViews != null) { - htmlViews.removeElementAt(index); - } - updateHtmlViews(index); + updateHtmlViews(index, false); } else if (name == "tabLayoutPolicy") { BasicTabbedPaneUI.this.uninstallUI(pane); BasicTabbedPaneUI.this.installUI(pane); @@ -3584,13 +3579,13 @@ calculatedBaseline = false; } else if (name == "indexForNullComponent") { isRunsDirty = true; - updateHtmlViews((Integer)e.getNewValue()); + updateHtmlViews((Integer)e.getNewValue(), true); } else if (name == "font") { calculatedBaseline = false; } } - private void updateHtmlViews(int index) { + private void updateHtmlViews(int index, boolean inserted) { String title = tabPane.getTitleAt(index); boolean isHTML = BasicHTML.isHTMLString(title); if (isHTML) { @@ -3598,16 +3593,24 @@ htmlViews = createHTMLVector(); } else { // Vector already exists View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.insertElementAt(v, index); + setHtmlView(v, inserted, index); } } else { // Not HTML if (htmlViews!=null) { // Add placeholder - htmlViews.insertElementAt(null, index); + setHtmlView(null, inserted, index); } // else nada! } updateMnemonics(); } + private void setHtmlView(View v, boolean inserted, int index) { + if (inserted || index >= htmlViews.size()) { + htmlViews.insertElementAt(v, index); + } else { + htmlViews.setElementAt(v, index); + } + } + // // ChangeListener // @@ -3726,7 +3729,7 @@ return; } isRunsDirty = true; - updateHtmlViews(tp.indexOfComponent(child)); + updateHtmlViews(tp.indexOfComponent(child), true); } public void componentRemoved(ContainerEvent e) { JTabbedPane tp = (JTabbedPane)e.getContainer();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JTabbedPane/8017284/bug8017284.java Fri Aug 08 16:19:36 2014 +0400 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.BorderLayout; +import java.awt.Toolkit; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.plaf.metal.MetalLookAndFeel; +import sun.awt.SunToolkit; + +/** + * @test + * @bug 8017284 + * @author Alexander Scherbatiy + * @summary Aqua LaF: memory leak when HTML is used for JTabbedPane tab titles + * @run main/othervm/timeout=60 -Xmx128m bug8017284 + */ +public class bug8017284 { + + private static final int TAB_COUNT = 100; + private static final int ITERATIONS = 100; + private static JFrame frame; + private static JTabbedPane tabbedPane; + + public static void main(String[] args) throws Exception { + + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame(); + frame.setSize(500, 500); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + tabbedPane = new JTabbedPane(); + + for (int i = 0; i < TAB_COUNT; i++) { + tabbedPane.add("Header " + i, new JLabel("Content: " + i)); + } + + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(tabbedPane, BorderLayout.CENTER); + frame.setVisible(true); + }); + + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + + SwingUtilities.invokeAndWait(() -> { + for (int j = 0; j < ITERATIONS; j++) { + for (int i = 0; i < TAB_COUNT; i++) { + tabbedPane.setTitleAt(i, getHtmlText(j * TAB_COUNT + i)); + } + } + }); + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + + SwingUtilities.invokeAndWait(() -> frame.dispose()); + } + + private static String getHtmlText(int i) { + return "<html><b><i>" + i + "</b></i>"; + } +}