-
Bug
-
Resolution: Not an Issue
-
P2
-
None
-
1.2.1, 1.3.0
-
generic, x86
-
generic, windows_nt
Name: skT88420 Date: 10/11/99
Using Kestrel RA
The attached program shows a memory leak in JMenuBar.
Using the add button, add X panels. These panel will each as a menu to the menubar. Now, remove them using the remove button, these will remove the panels and their associated menubar. Using the "Main" menu, collect the trash. You will notice that panel X is never collected, while panels 1 through X-1 are collected.
Add more panels. Call the total number of panels added since application start Y. Collect the garbage. Panel X is now garbage collected, while panel Y is not. This process can be repeated indefinitely.
Commenting the line in SPanel where the action is added to the menu and the problem goes away. This issue is referenced in the code with "COMMENT1".
--
Another issue that this brings up is that the menubar MUST be repainted after a menu is deleted. I do not know if this is a bug or not, but it seems like this should be handled automatically.
This issue is referenced in the code with "COMMENT2".
CODE:
---------------
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.border.*;
import java.beans.*;
final public class SunTest15 extends JFrame {
private JTabbedPane tabbedPane;
private int count = 0;
private JMenuBar menubar;
public SunTest15() {
super("Memory leak in JMenu");
JPanel panel = new JPanel(new BorderLayout());
JPanel p = new JPanel();
JButton b;
b = new JButton("Add");
b.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
addPanel();
}
});
p.add(b);
b = new JButton("Remove");
b.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
removePanel();
}
});
p.add(b);
panel.add(p,BorderLayout.NORTH);
tabbedPane = new JTabbedPane();
panel.add(tabbedPane,BorderLayout.CENTER);
getContentPane().add(panel);
menubar = new JMenuBar();
Action a = new AbstractAction("Collect garbage") {
public void actionPerformed(ActionEvent e) {
System.gc();
}
};
JMenu menu = new JMenu("Main");
menu.add(a);
menubar.add( menu );
setJMenuBar(menubar);
pack();
setSize(400,300);
show();
}
private void addPanel() {
SPanel sp = new SPanel(++count,menubar);
sp.add(new JLabel("Panel"));
tabbedPane.addTab("Tab: " + count,sp);
}
private void removePanel() {
int index = tabbedPane.getTabCount();
if (index != 0) {
//System.out.println("removePanel: " + (index - 1));
SPanel sp = (SPanel)tabbedPane.getComponentAt(index - 1);
menubar.remove(sp.getMenu());
tabbedPane.removeTabAt(index - 1);
}
//COMMENT2
//This line is necessary to repaint the menubar after removing an item.
menubar.repaint();
System.gc();
}
public static void main(String[] args) {
SunTest15 s = new SunTest15();
s.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public static class SPanel extends JPanel {
private JMenu menu;
private int count;
public SPanel(int count, JMenuBar menubar) {
this.count = count;
menu = new JMenu("panel " + count);
Action a = new AbstractAction("Action") {
public void actionPerformed(ActionEvent e) {
System.out.println("Action");
}
};
//COMMENT1
//Comment out the following line and the problem goes away.
menu.add(a);
menubar.add(menu);
}
public JMenu getMenu() {
return menu;
}
public void finalize() throws Throwable {
System.out.println("Finalizing panel " + count);
super.finalize();
}
}
}
(Review ID: 96376)
======================================================================
- duplicates
-
JDK-4246299 Memory leaks prohibiting top level windows to be GC'ed
- Closed