-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
1.4.0, 1.4.1
-
x86
-
windows_2000, windows_xp
Name: jk109818 Date: 09/16/2002
FULL PRODUCT VERSION :
java version "1.4.1-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
Service Pack 2
A DESCRIPTION OF THE PROBLEM :
I seem to have found a memory leak with JDesktop and
JInternalFrame on JDK1.4.x.
If you run the sample application below under a heap
profiler, and close all of
the internal frames, you will see that one of the internal
frames is never
destroyed. The order of closing doesn't seem to matter.
It's always the first
frame added to the desktop ("internal0") that is leaked.
Note that the internal
frame's dispose() method *is* called -- I verified this
under the debugger -- yet
still somebody is holding a reference.
I can also reproduce this bug with
the "InternalFrameEventDemo.java" application
from sun's tutorial site (with the DisplayWindow modified
to be closeable).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the sample application below, under a
heap profiler
2. Close all of the internal frames, in any order
3. Inspect objects under the profiler. One of the
JInternalFrames (the first to be added to the desktop) was
not destroyed and still has live back-references.
EXPECTED VERSUS ACTUAL BEHAVIOR :
All of the JInternalFrames should have been destroyed.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.Dimension;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JDesktopPane desktop = new JDesktopPane();
desktop.setPreferredSize(new Dimension(400,400));
frame.setContentPane(desktop);
for (int i = 0; i < 5; i++) {
JInternalFrame internal = new JInternalFrame("internal"+i, true, true);
internal.setPreferredSize(new Dimension(200,200));
internal.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
desktop.add(internal);
internal.pack();
internal.show();
}
frame.pack();
frame.show();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
I don't know of a workaround, but you can at least reduce
the severity of the leak. Since the JInternalFrame's
dispose() method *is* called, an application subclassing
the internal frame can release its object references at
that point (to avoid leaking everything the frame holds
onto along with the frame).
(Review ID: 164068)
======================================================================
Name: jk109818 Date: 09/25/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)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2915]
ADDITIONAL OPERATING SYSTEMS :
Redhat Linux 7.3
A DESCRIPTION OF THE PROBLEM :
Using any Look and Feel Derived from BasicLookAndFeel the
first JInternalFrame is always referenced by the UIManager.
The BasicInternalFrameUI lazely creates an ActionMap
for the UIManager until the first BasicInternalFrameUI
installUI is called and then adds the action map to the
UIManager defaults table. In the creation of the map
BasicInternalFrameUI creates an ananymous inner class and
adds the inner class as a value in the ActionMap for the
key "showSystemMenu". Subsequent calls to installUI use
the default map stored in UIManager.
1. The UIManager defaults table (a static member of
UIManager) holds a refernce to the anonymous inner class
created in BasicInternalFrameUI.createActionMap
2. The inner class holds a reference to the
BasicInternalFrameUI due to it being an inner class
4. All BasicInternalFrameUIs hold a reference to its
JInternalFrame via its frame member.
5. The first JInternalFrame that called installUI for
itself is referenced via the static defaults table of
UIManager and is never GCed.
Following code is from BasicInternalFrameUI
public void installUI(JComponent c) {
frame = (JInternalFrame)c;
installDefaults();
installListeners();
installComponents();
installKeyboardActions();
frame.setOpaque(true);
}
protected void installKeyboardActions(){
if (internalFrameListener == null)
createInternalFrameListener();
frame.addInternalFrameListener
(internalFrameListener);
ActionMap actionMap = getActionMap();
SwingUtilities.replaceUIActionMap(frame, actionMap);
}
ActionMap getActionMap() {
ActionMap map = (ActionMap)UIManager.get
("InternalFrame.actionMap");
if (map == null) {
map = createActionMap();
if (map != null) {
UIManager.getLookAndFeelDefaults().put
("InternalFrame.actionMap",
map);
}
}
return map;
}
ActionMap createActionMap() {
ActionMap map = new ActionMapUIResource();
// add action for the system menu
map.put("showSystemMenu", new AbstractAction(){
public void actionPerformed(ActionEvent e){
titlePane.showSystemMenu();
}
public boolean isEnabled(){
return isKeyBindingActive();
}
});
// Set the ActionMap's parent to the Auditory Feedback
Action Map
BasicLookAndFeel lf = (BasicLookAndFeel)
UIManager.getLookAndFeel();
ActionMap audioMap = lf.getAudioActionMap();
map.setParent(audioMap);
return map;
}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a JInternalFrame with no references
new JInternalFrame();
2. Use OptimizeIt (or any other debugging tool) to see if
the above created JInternalFrame is destroyed.
Can also add a finalizer to JInternalFrame to see if the
frame is GCed for step 1
EXPECTED VERSUS ACTUAL BEHAVIOR :
The first JInternalFrame would get GCed when all non-swing
references are removed.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
public class TestInternalFrame {
static public void main(String [] args) {
new JInternalFrame() {
public void finalize() { System.out.println("First
Finialized"); }
};
System.gc();
new JInternalFrame() {
public void finalize() { System.out.println("Second
Finialized"); }
};
System.gc();
new JInternalFrame() {
public void finalize() { System.out.println("Third
Finialized"); }
};
System.gc();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Create a JInternalFrame early (after the LookAndFeel is
set) in the application that will not hold references to
any other objects.
(Review ID: 164966)
======================================================================
Name: jk109818 Date: 02/24/2003
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]
Service Pack 1
ADDITIONAL OPERATING SYSTEMS :
Also on Windows 2000, unknown service pack
A DESCRIPTION OF THE PROBLEM :
The first JInternalFrame created (via new
JInternalFrame(..)) never gets garbage collected. Frames
created after the first one do get collected normally.
The example program demonstrates this using an extension of
JInternalFrame with a printout in the finalize() method. Two
frames are created and then both are set back to null.
System.gc() is then called to request collection. The second
frame is collected then, but the first is not.
For an added test, I then ran the system out of memory to
prove that it is not getting collected. The first frame
never gets finalized before the application throws and
OutOfMemoryError.
While this depends on printouts in the finalize method, the
same results can also be seen by using the "hprof" heap
profiler in the JRE. The first JInternalFrame will exist on
the heap at program exit.
While this is not a terrible problem for straight use of
JInternalFrames, use of any extension thereof that retains
references to high-memory footprint objects will create
great frustration without applying the workaround.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the test program included, or inspect the
heap on any program that creates JInternalFrame objects
2. The printouts will show that the first frame is never
finalized but the second one is.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:
Both frames should get finalized and GC'd after the call to
System.gc(). At the very least, they should both be
collected by the time the system runs out of memory.
Actual:
Only the second frame is finalized and GC'd. This can also
be seen on a heap profile.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
public class test {
static class myframe extends JInternalFrame {
String id;
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Finalizing " + id);
}
}
public static void main(String[] args) throws Exception {
myframe f1, f2;
f1 = new myframe();
f1.id = "First";
f2 = new myframe();
f2.id = "Second";
f1 = null;
f2 = null;
System.gc();
java.util.Vector v = new java.util.Vector();
int i = 0;
while (true) {
v.add("Consume Memory " + i++);
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Create a new JInternalFrame at the beginning of the
application before using any extensions of JInternalFrame
which have references to objects which consume large amounts
of memory.
(Review ID: 181526)
======================================================================
FULL PRODUCT VERSION :
java version "1.4.1-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]
Service Pack 2
A DESCRIPTION OF THE PROBLEM :
I seem to have found a memory leak with JDesktop and
JInternalFrame on JDK1.4.x.
If you run the sample application below under a heap
profiler, and close all of
the internal frames, you will see that one of the internal
frames is never
destroyed. The order of closing doesn't seem to matter.
It's always the first
frame added to the desktop ("internal0") that is leaked.
Note that the internal
frame's dispose() method *is* called -- I verified this
under the debugger -- yet
still somebody is holding a reference.
I can also reproduce this bug with
the "InternalFrameEventDemo.java" application
from sun's tutorial site (with the DisplayWindow modified
to be closeable).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the sample application below, under a
heap profiler
2. Close all of the internal frames, in any order
3. Inspect objects under the profiler. One of the
JInternalFrames (the first to be added to the desktop) was
not destroyed and still has live back-references.
EXPECTED VERSUS ACTUAL BEHAVIOR :
All of the JInternalFrames should have been destroyed.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.awt.Dimension;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame("frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JDesktopPane desktop = new JDesktopPane();
desktop.setPreferredSize(new Dimension(400,400));
frame.setContentPane(desktop);
for (int i = 0; i < 5; i++) {
JInternalFrame internal = new JInternalFrame("internal"+i, true, true);
internal.setPreferredSize(new Dimension(200,200));
internal.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
desktop.add(internal);
internal.pack();
internal.show();
}
frame.pack();
frame.show();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
I don't know of a workaround, but you can at least reduce
the severity of the leak. Since the JInternalFrame's
dispose() method *is* called, an application subclassing
the internal frame can release its object references at
that point (to avoid leaking everything the frame holds
onto along with the frame).
(Review ID: 164068)
======================================================================
Name: jk109818 Date: 09/25/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)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2915]
ADDITIONAL OPERATING SYSTEMS :
Redhat Linux 7.3
A DESCRIPTION OF THE PROBLEM :
Using any Look and Feel Derived from BasicLookAndFeel the
first JInternalFrame is always referenced by the UIManager.
The BasicInternalFrameUI lazely creates an ActionMap
for the UIManager until the first BasicInternalFrameUI
installUI is called and then adds the action map to the
UIManager defaults table. In the creation of the map
BasicInternalFrameUI creates an ananymous inner class and
adds the inner class as a value in the ActionMap for the
key "showSystemMenu". Subsequent calls to installUI use
the default map stored in UIManager.
1. The UIManager defaults table (a static member of
UIManager) holds a refernce to the anonymous inner class
created in BasicInternalFrameUI.createActionMap
2. The inner class holds a reference to the
BasicInternalFrameUI due to it being an inner class
4. All BasicInternalFrameUIs hold a reference to its
JInternalFrame via its frame member.
5. The first JInternalFrame that called installUI for
itself is referenced via the static defaults table of
UIManager and is never GCed.
Following code is from BasicInternalFrameUI
public void installUI(JComponent c) {
frame = (JInternalFrame)c;
installDefaults();
installListeners();
installComponents();
installKeyboardActions();
frame.setOpaque(true);
}
protected void installKeyboardActions(){
if (internalFrameListener == null)
createInternalFrameListener();
frame.addInternalFrameListener
(internalFrameListener);
ActionMap actionMap = getActionMap();
SwingUtilities.replaceUIActionMap(frame, actionMap);
}
ActionMap getActionMap() {
ActionMap map = (ActionMap)UIManager.get
("InternalFrame.actionMap");
if (map == null) {
map = createActionMap();
if (map != null) {
UIManager.getLookAndFeelDefaults().put
("InternalFrame.actionMap",
map);
}
}
return map;
}
ActionMap createActionMap() {
ActionMap map = new ActionMapUIResource();
// add action for the system menu
map.put("showSystemMenu", new AbstractAction(){
public void actionPerformed(ActionEvent e){
titlePane.showSystemMenu();
}
public boolean isEnabled(){
return isKeyBindingActive();
}
});
// Set the ActionMap's parent to the Auditory Feedback
Action Map
BasicLookAndFeel lf = (BasicLookAndFeel)
UIManager.getLookAndFeel();
ActionMap audioMap = lf.getAudioActionMap();
map.setParent(audioMap);
return map;
}
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a JInternalFrame with no references
new JInternalFrame();
2. Use OptimizeIt (or any other debugging tool) to see if
the above created JInternalFrame is destroyed.
Can also add a finalizer to JInternalFrame to see if the
frame is GCed for step 1
EXPECTED VERSUS ACTUAL BEHAVIOR :
The first JInternalFrame would get GCed when all non-swing
references are removed.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
public class TestInternalFrame {
static public void main(String [] args) {
new JInternalFrame() {
public void finalize() { System.out.println("First
Finialized"); }
};
System.gc();
new JInternalFrame() {
public void finalize() { System.out.println("Second
Finialized"); }
};
System.gc();
new JInternalFrame() {
public void finalize() { System.out.println("Third
Finialized"); }
};
System.gc();
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Create a JInternalFrame early (after the LookAndFeel is
set) in the application that will not hold references to
any other objects.
(Review ID: 164966)
======================================================================
Name: jk109818 Date: 02/24/2003
FULL PRODUCT VERSION :
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
FULL OPERATING SYSTEM VERSION :
Microsoft Windows XP [Version 5.1.2600]
Service Pack 1
ADDITIONAL OPERATING SYSTEMS :
Also on Windows 2000, unknown service pack
A DESCRIPTION OF THE PROBLEM :
The first JInternalFrame created (via new
JInternalFrame(..)) never gets garbage collected. Frames
created after the first one do get collected normally.
The example program demonstrates this using an extension of
JInternalFrame with a printout in the finalize() method. Two
frames are created and then both are set back to null.
System.gc() is then called to request collection. The second
frame is collected then, but the first is not.
For an added test, I then ran the system out of memory to
prove that it is not getting collected. The first frame
never gets finalized before the application throws and
OutOfMemoryError.
While this depends on printouts in the finalize method, the
same results can also be seen by using the "hprof" heap
profiler in the JRE. The first JInternalFrame will exist on
the heap at program exit.
While this is not a terrible problem for straight use of
JInternalFrames, use of any extension thereof that retains
references to high-memory footprint objects will create
great frustration without applying the workaround.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile and run the test program included, or inspect the
heap on any program that creates JInternalFrame objects
2. The printouts will show that the first frame is never
finalized but the second one is.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:
Both frames should get finalized and GC'd after the call to
System.gc(). At the very least, they should both be
collected by the time the system runs out of memory.
Actual:
Only the second frame is finalized and GC'd. This can also
be seen on a heap profile.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import javax.swing.*;
import java.awt.*;
public class test {
static class myframe extends JInternalFrame {
String id;
protected void finalize() throws Throwable {
super.finalize();
System.out.println("Finalizing " + id);
}
}
public static void main(String[] args) throws Exception {
myframe f1, f2;
f1 = new myframe();
f1.id = "First";
f2 = new myframe();
f2.id = "Second";
f1 = null;
f2 = null;
System.gc();
java.util.Vector v = new java.util.Vector();
int i = 0;
while (true) {
v.add("Consume Memory " + i++);
}
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Create a new JInternalFrame at the beginning of the
application before using any extensions of JInternalFrame
which have references to objects which consume large amounts
of memory.
(Review ID: 181526)
======================================================================
- duplicates
-
JDK-4836639 Creating components in XP L&F throws OutOfMemoryError.
- Resolved
- relates to
-
JDK-8068307 Test javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java fails with GTKL&F
- Open
-
JDK-4759312 JInternalFrame Not Being Finalized After Closing
- Closed