Suppose I subclass JPanel
, and my subclass uses a lot of memory.
What is the right way for me to design this class so that the memory resources are freed when my JPanel is used as a component in a larger system?
Seems like there's a few options:
- subclass
finalize()
(red flags all over the place -- the literature I've read says you shouldn't get into the finalizing business) - add an explicit
dispose()
ordestroy()
or whatever, for consumers of my class to use - add some kind of listener to my JPanel that gets notified when the parent gets disposed
- override some method of JPanel which will automatically get called when their parent window gets disposed
In the example below I used the finalize()
option, which works but only when garbage collection gets called, and there are instances where I'd rather the cleanup happens when the JPanel is no longer needed.
Option #2 is nice, but then I have to rely on consumers to call this method, and the Swing philosophy seems to be just stick components into a window, and let all the components get destroyed when the window gets closed. So if my JPanel is inside a JTable in a JScrollPane in a JPanel in a JFrame, chances are, the consumer of my class isn't going to call my dispose()
or destroy()
method.
Options #3 or #4 would be my choice but I can't find anything that seems to apply here.
Any suggestions?
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class JPanelMemoryHog extends JPanel
{
final private String title;
final private Object space;
public JPanelMemoryHog(String title)
{
super();
this.title = title;
this.space = new byte[5*1000*1000];
setBorder(BorderFactory.createTitledBorder(title));
setPreferredSize(new Dimension(300,200));
}
@Override protected void finalize()
{
System.out.println("finalized "+this.title);
}
public static void main(String[] args) {
JFrame frame = new JFrame("example");
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
JButton button = new JButton("create frame");
button.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
createFrame();
}
});
panel.add(button, BorderLayout.CENTER);
frame.setContentPane(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private static int panelcount = 0;
protected static void createFrame() {
final String title = "panel"+(++panelcount);
final JFrame frame = new JFrame(title);
frame.setContentPane(new JPanelMemoryHog(title));
frame.pack();
frame.addWindowListener(new WindowAdapter() {
@Override public void windowClosing(WindowEvent e) {
System.out.println("closing "+title);
frame.dispose();
}
});
frame.setVisible(true);
}
}