JDK-4726458 : Dialogs and Frames are never garbage collected
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_98,windows_2000
  • CPU: x86
  • Submitted: 2002-08-05
  • Updated: 2007-07-25
  • Resolved: 2011-05-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6-poolResolved 7 b17Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
Name: rmT116609			Date: 08/05/2002


FULL PRODUCT VERSION :
C:\temp\bug>java -version
java version "1.4.1-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-beta-b14)
Java HotSpot(TM) Client VM (build 1.4.1-beta-b14, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Attached is sample code that causes a memory leak under 1.3 and 1.4.1. This sample adds one line of code to the already closed bug 4495338.

This bug is causing us to have a major memory leak in our application.

This bug also causes Frames and Dialogs to keep the JVM from exiting once all the frames are closed and disposed. 

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. javac TestCase.java
2. java TestCase

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected:
Dialog1 being finalized
Dialog2 being finalized
Dialog3 being finalized

Got:
Dialog1 being finalized
Dialog2 being finalized


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.*;

class TestDialog extends JDialog {
    String name;
    public TestDialog(String name) {
        this.name = name;
    }
    public void show() {
        super.show();
        dispose(); // so no user interaction is needed
    }
    public void finalize() {
        System.out.println(name + " being finalized");
    }
}


public class TestCase {
    public static void main(String[] arg) {
        TestDialog dialog1 = new TestDialog("Dialog1");
        TestDialog dialog2 = new TestDialog("Dialog2");
        TestDialog dialog3 = new TestDialog("Dialog3");

        // do nothing to Dialog1

        // pack Dialog2
        dialog2.pack(); //this is empty size 0,0
        dialog2.dispose();

        // show Dialog3
        dialog3.setSize(200,200); //added this line
        dialog3.show();

        // should be garbage collectable after this
        dialog1 = null;
        dialog2 = null;
        dialog3 = null;

        for (int i = 0; i < 20; i++)
            System.gc();

        System.exit(0);
    }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use no more than one JFrame or JDialog in your application.
(Review ID: 160375) 
======================================================================

Comments
SUGGESTED FIX webrev at http://javaweb.sfbay/jcg/7/awt/4726458/ and also attached yo the CR
25-06-2007

EVALUATION to fix the problem we should deny focus events arrived to non-focusable/non-visible/non-showing components/windows Also I've noticed thet we may keep reference to window in XGlobalCursorManager.nativeContainer.
07-06-2007

EVALUATION Contribution-Forum:https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?messageID=12045&forumID=1463
16-03-2006

EVALUATION Should fix this in Tiger (memory footprint). ###@###.### 2002-08-05 Is not able to reproduce the problem in 1.4 and 1.4.1. But was able to reproduce the problem in 1.3.1, but not consistently. When i ran it 10 times, i was able to reproduce it 2 times. ###@###.### 2002-08-08 According to OptimizeIt, the TestDialog is being referenced from KeyboardFocusManager. I did discover that as soon as another Frame is shown, KeyboardFocusManager points to it and the last TestDialog can then be garbage collected. I added the following code to the test case: JFrame jf = new JFrame("JFrame"); jf.getContentPane().add(new JButton("JButton")); jf.setSize(200, 200); jf.show(); So it's not necessary to limit yourself to just one JFrame or JDialog - we only leak 1 Window no matter how many you create. But if you create a JFrame, dispose it, and want to continue with your app using no Frames at all, we do hold onto that Frame when we shouldn't. ###@###.### 2002-08-14 There are two problems here: 1) we don't receive sometimes WINDOW_DEACTIVATED/WINDOW_LOST_FOCUS when window closes on Windows. I noticed that this happens on Windows 2000 when you start java and switch to some other window and start typing there. In that case, Java windows appear on task bar flashing - it receives WINDOW_ACTIVATED at the moment! But, if you dispose it at once it won't receive WINDOW_LOST_FOCUS. 2) Event when we receive all the events we don't clear focusCycleRoot and permanentFocusOwner sometimes, those are static variables which keep references to some components. ###@###.### 2002-12-16 After I resolved the problems with missing events and static fields there is still something that keeps the reference to the Window - Java doesn't exit. I found that it is IM - (sun.awt.im.InputMethodContext).inputMethod -> (sun.awt.windows.WInputMethod).inputContext -> (sun.awt.im.InputMethodContext).currentClientComponent -> TestDialog . I don't why IM is keeping the component because as I see from the logs all necessary focus events(focus losts) arrived. ###@###.### 2002-12-16 Another references to TestDialogs: (sun.awt.windows.WInputMethod).awtFocussedComponent (sun.awt.windows.WInputMethod).clientComponent ###@###.### 2002-12-16 IM keeps the reference to disposed component because it received FOCUS_GAINED after component was disposed of. This happens becuase window is being dispose right after show - so events are not yet dispatched when window has been disposed of. I added check for isShowing() to InputContext.focusGained and those references disappeared from the dump. However, Java still doesn't exit. In the dump, I see that someone is keeping the reference to WFramePeer. ###@###.### 2002-12-17 The last peer is the peer of SwingUtilities.sharedOwnerFrame instance. It was created by call to Window.addNotify(or pack()). This instance lies in static variable of SwingUtilities and is never been disposed of. Because AWTAutoShutdown sees that there is alive peer exists it doesn't shut AWT down. ###@###.### 2002-12-17 After I applied fix for focus event, input method static field and disposed of Swing frame refence program successfully exited. There is a small problem exists which should be resolved as well - that sharedOwnerFrame has "synchronized" dispose method which can lead to deadlocks. It should be changed as well. ###@###.### 2002-12-18 This is pretty involved. We may have to target a post-Tiger release. ###@###.### 2003-10-10 Should check if it is still reproducible after Mustang beta. ###@###.### 2005-1-27 14:16:54 GMT It's reproducible with Mustang b37 on Windows XP. ###@###.### 2005-06-20 14:38:18 GMT We are not able to fix it in Mustang, unfortunately. ###@###.### 2005-07-01 11:39:24 GMT
20-06-2005

CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mustang
17-09-2004