/* * Copyright (c) 1997, 2024, 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. */ /* * @test * @key headful * @requires (os.family != "linux") * @bug 4119609 4149812 4136116 4171960 4170095 4294016 4343272 * @summary This test verifies that java.awt objects are being garbage * collected correctly. That is, it ensures that unneeded * references (such as JNI global refs or refs in static arrays) * do not remain after the object is disposed. * @run main/othervm ComponentLeakTest */ import java.awt.BorderLayout; import java.awt.Button; import java.awt.Canvas; import java.awt.CardLayout; import java.awt.Checkbox; import java.awt.CheckboxGroup; import java.awt.CheckboxMenuItem; import java.awt.Choice; import java.awt.Color; import java.awt.Component; import java.awt.Dialog; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Frame; import java.awt.Graphics; import java.awt.GraphicsConfiguration; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Label; import java.awt.LayoutManager; import java.awt.List; import java.awt.Menu; import java.awt.MenuBar; import java.awt.MenuItem; import java.awt.MenuShortcut; import java.awt.Panel; import java.awt.PopupMenu; import java.awt.ScrollPane; import java.awt.Scrollbar; import java.awt.TextArea; import java.awt.TextField; import java.awt.Window; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.Map; import java.util.HashMap; public class ComponentLeakTest { public static void main(String[] args) { final int iter = 5; for(int count = 0; count < iter; count++) { MainFrame f = new MainFrame(); MainWindow w = new MainWindow(f); MainDialog d = new MainDialog(f); TestFileDialog fd = new TestFileDialog(f, "TestFileDialog"); fd.addNotify(); // fd.show() hangs fd.dispose(); d.dispose(); w.dispose(); f.dispose(); } // Test layout managers Frame border = new Frame(); border.setLayout(new BorderLayout()); Frame card = new Frame(); card.setLayout(new CardLayout()); Frame flow = new Frame(); flow.setLayout(new FlowLayout()); Frame gridBag = new Frame(); gridBag.setLayout(new GridBagLayout()); Frame grid = new Frame(); grid.setLayout(new GridLayout(1, 2)); for (int count = 0; count < iter; count++) { border.add(new BorderTestButton("BorderTest"), BorderLayout.WEST); border.add(new BorderTestButton("BorderTest"), BorderLayout.EAST); card.add(new CardTestButton("CardTest"), "card0"); card.add(new CardTestButton("CardTest"), "card1"); flow.add(new FlowTestButton()); flow.add(new FlowTestButton()); gridBag.add(new GridBagTestButton(), new GridBagConstraints()); gridBag.add(new GridBagTestButton(), new GridBagConstraints()); grid.add(new GridTestButton()); grid.add(new GridTestButton()); border.removeAll(); card.removeAll(); flow.removeAll(); gridBag.removeAll(); grid.removeAll(); } gc(5); try { Thread.sleep(1000); } catch (InterruptedException ie) { } freeReferences(); reportLeaks(); System.err.println("Test passed."); } public static void initWindow(Window w) { w.setSize(600, 400); w.setLayout(new FlowLayout()); // peered components w.add(new TestButton("Button")); w.add(new TestCanvas()); w.add(new TestCheckbox("Checkbox", true)); TestChoice choice = new TestChoice(); choice.add("Choice 1"); choice.add("Choice Two"); w.add(choice); w.add(new TestLabel("Label")); TestList list = new TestList(); list.add("List 1"); list.add("List Two"); w.add(list); w.add(new TestScrollbar(Scrollbar.VERTICAL)); w.add(new TestScrollbar(Scrollbar.HORIZONTAL)); TestScrollPane scrollpane = new TestScrollPane(); scrollpane.add(new TestButton("Button in a scrollpane")); w.add(scrollpane); w.add(new TestTextArea("TextArea", 3, 30)); w.add(new TestTextField("TextField")); // nested components TestPanel panel1 = new TestPanel(); panel1.setLayout(new FlowLayout()); panel1.setBackground(Color.red); w.add(panel1); panel1.add(new TestButton("level 2")); Panel panel2 = new Panel(); panel2.setLayout(new FlowLayout()); panel2.setBackground(Color.green); panel1.add(panel2); panel2.add(new TestButton("level 3")); w.add(new TestLightweight("Lightweight")); } private static ReferenceQueue queue = new ReferenceQueue(); private static Map refs = new HashMap(); public static void register(Object obj) { PhantomReference ref = new PhantomReference(obj, queue); refs.put(ref, obj.getClass().getName()); } private static void gc() { System.gc(); try { Thread.sleep(100); } catch (InterruptedException ie) { throw new RuntimeException("Test was interrupted"); } } private static void gc(int num) { for (; num > 0; num--) { gc(); } } public static void freeReferences() { System.err.println("Total references: " + refs.size()); boolean wasFreed = false; do { Object[] arr = new Object[2000]; gc(5); Reference ref = null; wasFreed = false; while ((ref = queue.poll()) != null) { refs.remove(ref); wasFreed = true; gc(); } } while (wasFreed); } public static void reportLeaks() { for (Reference ref : refs.keySet()) { System.err.println("Leaked " + refs.get(ref)); } if (refs.size() > 0) { throw new RuntimeException("Some references remained: " + refs.size()); } } } class TestFrame extends Frame { public TestFrame() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestFrame(String title) { super(title); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestWindow extends Window { public TestWindow(Frame owner) { super(owner); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestWindow(Window owner) { super(owner); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestDialogL extends Dialog { public TestDialogL(Frame owner) { super(owner); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Frame owner, boolean modal) { super(owner, modal); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Frame owner, String title) { super(owner, title); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Frame owner, String title, boolean modal) { super(owner, title, modal); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Dialog owner) { super(owner); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Dialog owner, String title) { super(owner, title); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestDialogL(Dialog owner, String title, boolean modal) { super(owner, title, modal); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestFileDialog extends FileDialog { public TestFileDialog(Frame parent) { super(parent); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestFileDialog(Frame parent, String title) { super(parent, title); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestFileDialog(Frame parent, String title, int mode) { super(parent, title, mode); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestButton extends Button { public TestButton() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestButton(String title) { super(title); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestCanvas extends Canvas { int width = 100; int height = 100; public TestCanvas() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestCanvas(GraphicsConfiguration config) { super(config); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public void paint(Graphics g) { g.setColor(Color.blue); g.fillRoundRect(10, 10, 50, 50, 15, 30); g.setColor(Color.red); g.fillOval(70, 70, 25, 25); } public Dimension getPreferredSize() { return new Dimension(width, height); } } class TestCheckbox extends Checkbox { public TestCheckbox() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestCheckbox(String label) { super(label); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestCheckbox(String label, boolean state) { super(label, state); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestCheckbox(String label, boolean state, CheckboxGroup group) { super(label, state, group); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestCheckbox(String label, CheckboxGroup group, boolean state) { super(label, group, state); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestChoice extends Choice { public TestChoice() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestLabel extends Label { public TestLabel() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestLabel(String text) { super(text); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestLabel(String text, int align) { super(text, align); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestList extends List { public TestList() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestList(int rows) { super(rows); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestList(int rows, boolean multipleMode) { super(rows, multipleMode); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestScrollbar extends Scrollbar { public TestScrollbar() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestScrollbar(int orientation) { super(orientation); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestScrollbar(int orient, int val, int visible, int min, int max) { super(orient, val, visible, min, max); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestScrollPane extends ScrollPane { public TestScrollPane() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestScrollPane(int policy) { super(policy); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestTextField extends TextField { public TestTextField() { ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextField(String text) { super(text); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextField(int columns) { super(columns); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextField(String text, int columns) { super(text, columns); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } } class TestTextArea extends TextArea { public TestTextArea() { ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextArea(String text) { super(text); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextArea(int rows, int columns) { super(rows, columns); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextArea(String text, int rows, int columns) { super(text, rows, columns); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } public TestTextArea(String text, int rows, int columns, int bars) { super(text, rows, columns, bars); ComponentLeakTest.register(this); requestFocus(); setDropTarget(new TestDropTarget(this)); } } class TestPanel extends Panel { public TestPanel() { ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } public TestPanel(LayoutManager layout) { super(layout); ComponentLeakTest.register(this); setDropTarget(new TestDropTarget(this)); } } class TestMenu extends Menu { public TestMenu() { ComponentLeakTest.register(this); } public TestMenu(String label) { super(label); ComponentLeakTest.register(this); } public TestMenu(String label, boolean tearOff) { super(label, tearOff); ComponentLeakTest.register(this); } } class TestMenuItem extends MenuItem { public TestMenuItem() { ComponentLeakTest.register(this); } public TestMenuItem(String label) { super(label); ComponentLeakTest.register(this); } public TestMenuItem(String label, MenuShortcut s) { super(label, s); ComponentLeakTest.register(this); } } class TestMenuBar extends MenuBar { public TestMenuBar() { ComponentLeakTest.register(this); } } class TestPopupMenu extends PopupMenu { public TestPopupMenu() { ComponentLeakTest.register(this); } public TestPopupMenu(String label) { super(label); ComponentLeakTest.register(this); } } class TestCheckboxMenuItem extends CheckboxMenuItem { public TestCheckboxMenuItem() { ComponentLeakTest.register(this); } public TestCheckboxMenuItem(String label) { super(label); ComponentLeakTest.register(this); } public TestCheckboxMenuItem(String label, boolean state) { super(label, state); ComponentLeakTest.register(this); } } class BorderTestButton extends Button { public BorderTestButton() { ComponentLeakTest.register(this); } public BorderTestButton(String title) { super(title); ComponentLeakTest.register(this); } } class CardTestButton extends Button { public CardTestButton() { ComponentLeakTest.register(this); } public CardTestButton(String title) { super(title); ComponentLeakTest.register(this); } } class FlowTestButton extends Button { public FlowTestButton() { ComponentLeakTest.register(this); } public FlowTestButton(String title) { super(title); ComponentLeakTest.register(this); } } class GridBagTestButton extends Button { public GridBagTestButton() { ComponentLeakTest.register(this); } public GridBagTestButton(String title) { super(title); ComponentLeakTest.register(this); } } class GridTestButton extends Button { public GridTestButton() { ComponentLeakTest.register(this); } public GridTestButton(String title) { super(title); ComponentLeakTest.register(this); } } class TestLightweight extends Component { String label; int width = 100; int height = 30; public TestLightweight(String label) { this.label = label; ComponentLeakTest.register(this); } public void paint(Graphics g) { Dimension d = getSize(); g.setColor(Color.orange); g.fillRect(0, 0, d.width, d.height); g.setColor(Color.black); int x = 5; int y = (d.height - 5); g.drawString(label, x, y); } public Dimension getPreferredSize() { return new Dimension(width,height); } } class TestDropTarget extends DropTarget { public TestDropTarget(Component comp) { super(comp, new DropTargetListener() { public void dragEnter(DropTargetDragEvent dtde) {} public void dragOver(DropTargetDragEvent dtde) {} public void dropActionChanged(DropTargetDragEvent dtde) {} public void dragExit(DropTargetEvent dte) {} public void drop(DropTargetDropEvent dtde) {} }); ComponentLeakTest.register(this); } } class MainWindow extends TestWindow { public MainWindow(Frame f) { super(f); ComponentLeakTest.initWindow(this); setVisible(true); TestPopupMenu popup = new TestPopupMenu("hi"); add(popup); popup.show(this, 5, 5); } } class MainDialog extends TestDialogL { public MainDialog(Frame f) { super(f, "MainDialog", false); ComponentLeakTest.initWindow(this); setVisible(true); TestPopupMenu popup = new TestPopupMenu("hi"); add(popup); popup.show(this, 5, 5); } } class MainFrame extends TestFrame { public MainFrame(){ super("Component Leak Test MainFrame"); ComponentLeakTest.initWindow(this); TestMenu menu = new TestMenu("Print"); TestMenu menu2 = new TestMenu("File"); TestMenu menu3 = new TestMenu("Edit"); TestMenu menu4 = new TestMenu("ReallyReallyReallyReallyReallyReallyReallyReally" + "ReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLong"); menu2.setFont(new Font("SansSerif", Font.BOLD, 20)); menu2.setEnabled(false); menu3.setFont(new Font("Monospaced", Font.ITALIC, 18)); menu3.setEnabled(false); menu4.setEnabled(false); TestMenuItem itemPrinter = new TestMenuItem("foobar"); TestMenuItem itemScreen = new TestMenuItem("baz"); TestCheckboxMenuItem itemCheck = new TestCheckboxMenuItem("yep"); menu.add(itemPrinter); menu.add(itemScreen); menu.add(itemCheck); TestMenuBar menuBar = new TestMenuBar(); menuBar.add( menu ); menuBar.add( menu2 ); menuBar.add( menu3 ); menuBar.add( menu4 ); setMenuBar(menuBar); setVisible(true); TestPopupMenu popup = new TestPopupMenu("hi"); add(popup); popup.show(this, 5, 5); } }