FULL PRODUCT VERSION :
java version "1.5.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-b64)
Java HotSpot(TM) Client VM (build 1.5.0-b64, mixed mode, sharing)
ADDITIONAL OS VERSION INFORMATION :
Linux 2.6.5-mb1 #2 Tue Apr 20 13:22:26 IST 2004 i686 i686 i386 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
About 300 bytes are lost each time the JFrame in the sample code below
is disposed (in addition to the few accounted for by bug 6196089).
Test code adapted from application.
Perhaps not normally not much of an issue, but cumulative in an application
where windows are frequently opened and closed.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Using the test code, create and dispose of a set of 100 windows, say, 6 times.
Then garbage collect a few times. No matter how often it is done, you will
notice in hprof output either 600 or 601 (601 because of the first window)
instances of Hashtable$Entry, PhantomReference, and DefaultDisposerRecord
which are allocated in a variety of places are never collected, e.g.,
sun.java2d.DisposerRecord.<init>(DisposerRecord.java:14)
sun.java2d.DefaultDisposerRecord.<init>(DefaultDisposerRecord.java:18)
sun.java2d.Disposer.addRecord(Disposer.java:69)
sun.awt.X11Renderer.XCreateGC(X11Renderer.java:Unknown line)
sun.awt.X11Renderer.<init>(X11Renderer.java:59)
sun.awt.X11Renderer.getInstance(X11Renderer.java:51)
sun.awt.X11SurfaceData.makePipes(X11SurfaceData.java:501)
sun.awt.X11SurfaceData$X11WindowSurfaceData.<init>(X11SurfaceData.java:512)
sun.awt.X11SurfaceData.createData(X11SurfaceData.java:322)
sun.awt.X11GraphicsConfig.createSurfaceData(X11GraphicsConfig.java:380)
sun.awt.X11.XWindow.validateSurface(XWindow.java:872)
sun.awt.X11.XDecoratedPeer.setBounds(XDecoratedPeer.java:412)
java.awt.Component.reshapeNativePeer(Component.java:1924)
java.awt.Component.reshape(Component.java:1880)
java.awt.Component.setBounds(Component.java:1847)
java.awt.Window.setBounds(Window.java:2334)
java.awt.Window.setClientSize(Window.java:494)
java.awt.Window.pack(Window.java:480)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Amount of memory after garbage collection should remain fairly constant.
ACTUAL -
About 30k lost each time 100 windows created and disposed.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class LeakWindow
extends JFrame
{
private JTable table;
protected JScrollPane tablePane;
private JMenu menu1;
protected LeakWindow()
{
super("Leak Demo");
TableModel dataModel = new AbstractTableModel()
{
public int getColumnCount() { return 10; }
public int getRowCount() { return 10;}
public Object getValueAt(int row, int col)
{
return new Integer(row*col);
}
};
this.table = new JTable(dataModel);
this.tablePane = new JScrollPane(this.table);
this.table.setSize(this.table.getPreferredSize());
JViewport vp = this.tablePane.getViewport();
vp.setPreferredSize(new Dimension(
(int) vp.getPreferredSize().getWidth(),
(int) this.table.getPreferredSize().getHeight()));
this.menu1 = new JMenu("Menu");
JMenuItem menuItem1 = new JMenuItem("100 Windows");
this.menu1.add(menuItem1);
menuItem1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
for (int i = 0; i < 100; ++i)
{
LeakWindow win = new
LeakWindow();
win.show();
win.dispose();
}
}
});
JMenuItem menuItem2 = new JMenuItem("Garbage Collect");
this.menu1.add(menuItem2);
menuItem2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("before: "
+ (Runtime.getRuntime().totalMemory()
- Runtime.getRuntime().freeMemory()));
Runtime.getRuntime().gc();
System.out.println("after: "
+ (Runtime.getRuntime().totalMemory()
- Runtime.getRuntime().freeMemory()));
}
});
JMenuBar menuBar = new JMenuBar();
menuBar.add(this.menu1);
JPanel menuPanel = new JPanel(new BorderLayout());
menuPanel.add(menuBar, BorderLayout.CENTER);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
Container cp = getContentPane();
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(this.tablePane, BorderLayout.CENTER);
topPanel.add(menuPanel, BorderLayout.NORTH);
cp.add(topPanel, BorderLayout.NORTH);
pack();
}
public static void main(String args[])
{
LeakWindow first = new LeakWindow();
first.setDefaultCloseOperation(EXIT_ON_CLOSE);
first.show();
}
}
---------- END SOURCE ----------
###@###.### 2005-04-19 10:07:06 GMT