jdk-24/test/jdk/java/awt/Component/ComponentLeakTest/ComponentLeakTest.java
2024-09-30 22:09:39 +00:00

770 lines
21 KiB
Java

/*
* 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<Reference, String> refs = new HashMap<Reference, String>();
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);
}
}