-
Bug
-
Resolution: Fixed
-
P4
-
7u2
-
b28
-
generic, x86
-
generic, windows_xp
-
Not verified
Name: jk109818 Date: 10/07/2002
FULL PRODUCT VERSION :
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
and
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
FULL OPERATING SYSTEM VERSION :
Windows XP, Service Pack 1
A DESCRIPTION OF THE PROBLEM :
Related to Bug ID 4748141.
If a single JInternalFrame is added to a JDesktopPane and
then closed, the instance is not available for garbage
collection UNTIL a new JInternalFrame is added to the
desktop. It seems like even though the JInternalFrame has
been "disposed", a reference is still maintained to the
JInternalFrame as the selected window. When the new
JInternalFrame is added, the reference is shifted allowing
the "disposed" JInternalFrame to be garbage collected.
In essence, this is a memory leak.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code as shown in the Source Code section. Click
the "Add Frame" button, close the initial frame, and click
the "Garbage Collect" button (sets the state to what is
described in bug ID 4748141). Click the "Add Frame"
button, close the new frame, and click the "Garbage
Collect" button. Note in the output window that the
println() statement in the finalize() method of the custom
JInternalFrame class does not trigger. Now click the "Add
Frame" button followed by the "Garbage Collect" button.
You will see the println() statement in the finalize()
method of the original custom JInternalFrame() instance
trigger.
NOW, the original JInternalFrame is allowed to garbage
collect.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Should expect to see the finalize() method for the
JInternalFrame class to trigger after it has been disposed
of and the garbage collector fires.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class InternalFrameTest
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Internal Frame Test");
frame.getContentPane().setLayout(new BorderLayout());
final JDesktopPane desktopPane = new JDesktopPane();
desktopPane.setDesktopManager(new DefaultDesktopManager());
frame.getContentPane().add(desktopPane, BorderLayout.CENTER);
InternalFrameListener iFrameListener = new InternalFrameAdapter() {
public void internalFrameClosed(InternalFrameEvent evt)
{
System.out.println("Number of Frames Remaining=" +
desktopPane.getAllFrames().length);
}
};
// for (int i = 0; i < 10; i++) {
// JInternalFrame iFrame = new CustomInternalFrame("Frame " + i);
// iFrame.setSize(200, 200);
// iFrame.addInternalFrameListener(iFrameListener);
// desktopPane.add(iFrame);
// iFrame.setVisible(true);
// }
JButton button = new JButton("Add Frame");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
System.out.println("Adding new internal frame!");
CustomInternalFrame iFrame = new CustomInternalFrame("Dummy
Frame");
iFrame.setSize(200, 200);
desktopPane.add(iFrame);
iFrame.setVisible(true);
}
});
frame.getContentPane().add(button, BorderLayout.NORTH);
button = new JButton("Garbage Collect");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
System.out.println("Firing garbage collection!");
System.gc();
}
});
frame.getContentPane().add(button, BorderLayout.SOUTH);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
System.runFinalizersOnExit(true);
}
public static class CustomInternalFrame extends JInternalFrame
{
private static int iFrameIdCounter = 0;
private int iFrameId;
public CustomInternalFrame(String title)
{
super(title, true, true, true, true);
iFrameId = iFrameIdCounter++;
}
protected void finalize()
{
System.out.println("Discarding frame " + iFrameId);
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
None Identified
(Review ID: 165240)
======================================================================
FULL PRODUCT VERSION :
java version "1.4.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_01-b03)
Java HotSpot(TM) Client VM (build 1.4.0_01-b03, mixed mode)
and
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
FULL OPERATING SYSTEM VERSION :
Windows XP, Service Pack 1
A DESCRIPTION OF THE PROBLEM :
Related to Bug ID 4748141.
If a single JInternalFrame is added to a JDesktopPane and
then closed, the instance is not available for garbage
collection UNTIL a new JInternalFrame is added to the
desktop. It seems like even though the JInternalFrame has
been "disposed", a reference is still maintained to the
JInternalFrame as the selected window. When the new
JInternalFrame is added, the reference is shifted allowing
the "disposed" JInternalFrame to be garbage collected.
In essence, this is a memory leak.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the code as shown in the Source Code section. Click
the "Add Frame" button, close the initial frame, and click
the "Garbage Collect" button (sets the state to what is
described in bug ID 4748141). Click the "Add Frame"
button, close the new frame, and click the "Garbage
Collect" button. Note in the output window that the
println() statement in the finalize() method of the custom
JInternalFrame class does not trigger. Now click the "Add
Frame" button followed by the "Garbage Collect" button.
You will see the println() statement in the finalize()
method of the original custom JInternalFrame() instance
trigger.
NOW, the original JInternalFrame is allowed to garbage
collect.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Should expect to see the finalize() method for the
JInternalFrame class to trigger after it has been disposed
of and the garbage collector fires.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class InternalFrameTest
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Internal Frame Test");
frame.getContentPane().setLayout(new BorderLayout());
final JDesktopPane desktopPane = new JDesktopPane();
desktopPane.setDesktopManager(new DefaultDesktopManager());
frame.getContentPane().add(desktopPane, BorderLayout.CENTER);
InternalFrameListener iFrameListener = new InternalFrameAdapter() {
public void internalFrameClosed(InternalFrameEvent evt)
{
System.out.println("Number of Frames Remaining=" +
desktopPane.getAllFrames().length);
}
};
// for (int i = 0; i < 10; i++) {
// JInternalFrame iFrame = new CustomInternalFrame("Frame " + i);
// iFrame.setSize(200, 200);
// iFrame.addInternalFrameListener(iFrameListener);
// desktopPane.add(iFrame);
// iFrame.setVisible(true);
// }
JButton button = new JButton("Add Frame");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
System.out.println("Adding new internal frame!");
CustomInternalFrame iFrame = new CustomInternalFrame("Dummy
Frame");
iFrame.setSize(200, 200);
desktopPane.add(iFrame);
iFrame.setVisible(true);
}
});
frame.getContentPane().add(button, BorderLayout.NORTH);
button = new JButton("Garbage Collect");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt)
{
System.out.println("Firing garbage collection!");
System.gc();
}
});
frame.getContentPane().add(button, BorderLayout.SOUTH);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.setVisible(true);
System.runFinalizersOnExit(true);
}
public static class CustomInternalFrame extends JInternalFrame
{
private static int iFrameIdCounter = 0;
private int iFrameId;
public CustomInternalFrame(String title)
{
super(title, true, true, true, true);
iFrameId = iFrameIdCounter++;
}
protected void finalize()
{
System.out.println("Discarding frame " + iFrameId);
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
None Identified
(Review ID: 165240)
======================================================================
- backport of
-
JDK-8012004 JInternalFrame not being finalized after closing
- Closed
- relates to
-
JDK-4748141 First JInternalFrame added to a JDesktop causes memory leak
- Closed