Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java full version "1.5.0_03-b07" java full version "1.5.0_04-b05" java full version "1.6.0-ea-b44" java full version "1.4.2_08-b03" ADDITIONAL OS VERSION INFORMATION : SunOS snake 5.10 Generic_118844-08 i86pc i386 i86pc EXTRA RELEVANT SYSTEM CONFIGURATION : Stock W1100z all contract patched applied A DESCRIPTION OF THE PROBLEM : It appears that a possible circular reference or code issue via PhantomReference and/or WeakReference, prevents GC from completeing after a Frame.dispose() call until a focus/unfocus event on another Frame occurs. *) Note, tiny memory objects associated with normal Frame creation/disposal are never freed from the JVM runtime system might cause a 'stick' preventing full GC of a normally disposed Frame. This I beleive leads to the issue of applications not get fully garbage collected until a focus/unjfocus on another GUI item. The test case will if profiled will show 5MB pinned in the Heap when of course it could be free'd. The work around is explicit <var>=null the S_bigDummyData varible at the time of the Frame.dispose() call which is pretty unacceptible, and a real anti-Java practice. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Using any (decent) profiler we do the following (describes JVM 5.0) 1) Start Application (see source code below) 2) Hit the "Create New Frame" button once 3) Close the "popup Frame called "new sub frame" ALL MEMORY of the sub-frame should be FREE right now, however it doesn't get free'd until ... 4) Get the 'focus' on the Main Application Frame on/off a few time will ffree up some misc (another BUG to be reported) memory that may have been allocated with the Frame e.g. S_bigDummyData. *) Perform GC/and snapshot the current state as a baseline 6) Hit the "Create New Frame" button once 7) Close the "popup Frame called "new sub frame" *) Get the 'focus' on the Main Application Frame and 'unfocus' it to free up some misc (another BUG to be reported) memory that may have been allocated with the Frame e.g. S_bigDummyData. At this point we always show the following leaks one or more java.lang.ref.PhantomReference sun.java2d.DefaultDisposerRecord java.util.Hashtable$Entry java.lang.ref.SoftReference java.lang.ref.WeakReference sun.java2d.pipe.Region If YOU do not do a get/release focus on the main application's frame the S_bigDummyData byte array of about 5MB will not free up! (This will be opened in another BUG report). Note the get/release focus will free the 5MB for this simple example but will not free data that has a lot of complex references between multiple classes (which my test case can not show). So this is really two bugs, a small leak as described above and a LARGE temporary leak of data associated with sub-frames that only goes away when a 'focus' of the main application screen occurs. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The heap should free 5MB after step 3) above without requiring a focus/unfocus of another Frame. ACTUAL - 5MB heap is stuck and can not be GC'd without requiring a focus/unfocus of another Frame. ERROR MESSAGES/STACK TRACES THAT OCCUR : Not Applicable, this is a JVM heap leak REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- // CODE SUBMISSION IS FOR B) BELOW I WILL OPEN UP NEW BUGS // FOR THE OTHER ISSUES IN A FEW DAYS FOR PROPER BUGID // REFERENCES. // // Test Case XtoolkitIssue.java, shows two issues (A and B): // A) Tiny memory objects associated with normal Frame // creation/disposal are never freed from the JVM // runtime system might cause a 'stick' preventing GC // of a normally disposed Frame. // B) A LARGE temporary leak of data associated with // sub-frames that only goes away when a new 'focus' // to the main application screen occurs. The dispose() // method call of a given Frame should not require a // focus/unfocus of another GUI Frame to free up all // associated memory and or references. // C) An even more important issue is that large complex // applications (multi-window) that extend Frame/JFrame // may not actually get GC'd and thus cause memory // exhustion releated to A) above and possible circular // references via PhantomReference and/or WeakReference, // but this is beyond the scope of a simple test case // (only happens under Solaris 10 x86 with the XAWT // setting -Dawt.toolkit=sun.awt.X11.XToolkit). It // never happens under 1.4.2 or eariler. // // May be related to 6257260, 6245243, 6240100 - the synopsys // seems to support C) "The test is still fails if WeakRefs // are used. Seems that GC still doesn't clear heap area.", I // think 'the test' that is refered to doesn't fully excercise // the bug as a major application will work under JVM's 5.0 // and 6.0 if and only if XToolkit is NOT used, if XToolkit // is used we seem to get a GC leak that will quickly exhust // memory, the work around is explicit <var>=null to hundreds of // variables in eleven different classes at the time of a // Frame.dispose() call which is pretty unacceptible. // // ----------------------------------------------------- // The LEAK occurs under // // under Solaris 10 x86 with either // -Dawt.toolkit=sun.awt.X11.XToolkit // or // setenv AWT_TOOLKIT XToolkit // // uname -a (Stock W1100z with all contract patches) // SunOS snake 5.10 Generic_118844-08 i86pc i386 i86pc // // Under JVM's // java full version "1.5.0_03-b07" -> issues A) B) and C) // java full version "1.5.0_04-b05" -> issues A) B) and C) // java full version "1.6.0-ea-b44" -> issues A) B) and C) // java full version "1.4.2_08-b03" -> issues B) only // ----------------------------------------------------- // Using any (decent) profiler we do the following // 1) Start Application (see source code below) // 2) Hit the "Create New Frame" button once // 3) Close the "popup Frame called "new sub frame" // // ALL MEMORY of the sub-frame should be FREE // right now, however it doesn't get free'd until ... // // 4) Get the 'focus' on the Main Application Frame // on/off a few time will ffree up some misc (another BUG to be // reported) memory that may have been allocated with the // Frame e.g. S_bigDummyData. // *) Perform GC/and snapshot the current state as a baseline // 6) Hit the "Create New Frame" button once // 7) Close the "popup Frame called "new sub frame" // *) Get the 'focus' on the Main Application Frame // and 'unfocus' it to free up some misc (another BUG to be // reported) memory that may have been allocated with the // Frame e.g. S_bigDummyData. // // At this point we always show the following leaks one or more // java.lang.ref.PhantomReference // sun.java2d.DefaultDisposerRecord // java.util.Hashtable$Entry // java.lang.ref.SoftReference // java.lang.ref.WeakReference // sun.java2d.pipe.Region // // Now don't say this is fine, as it appears that it doesn't // really hurt as complex applications can unlike the freeing // of the S_bigDummyData on 'focus/unfocus' never free // data from the heap. // // If YOU do not do a get/release focus on the main application's // frame the S_bigDummyData byte array of about 5MB will not // free up! (This will be opened in another BUG report). Note // the get/release focus will free the 5MB for this simple example // but will not free data that has a lot of complex references between // multiple classes (which my test case can not show). // // So this is really two bugs, a small leak as described above // and a LARGE temporary leak of data associated with sub-frames // that only goes away when a 'focus' of the main application // screen occurs. // ----------------------------------------------------- // Note, if we remove // -Dawt.toolkit=sun.awt.X11.XToolkit // or // unsetenv AWT_TOOLKIT // then there is a still a tiny one (1) object "leak" in the form of // sun.awt.motif.MwindowAttributes // and the LARGE temporary leak (still exists) of data associated // with sub-frames that only goes away when a 'focus/unfocus' of // the main application screen occurs. // ----------------------------------------------------- // Note, if we use JDK 1.4 e.g. // java full version "1.4.2_08-b03" // there are still some tiny object "leak" in the form of // sun.awt.motif.MwindowAttributes (and others) // and the LARGE temporary leak (still exists) of data associated // with sub-frames that only goes away when a 'focus/unfocus' of // the main application screen occurs. import java.awt.*; import java.awt.image.*; import java.awt.event.*; public class XtoolkitIssue extends Frame implements WindowListener{ private boolean S_etype = true; private Button S_b = null; private static int S_offset = 100; public byte[] S_bigDummyData = null; public XtoolkitIssue(String name, boolean etype /* if true then exit app on windowClose() */){ S_etype = etype; setBounds(0,0,250,100); setVisible(true); setTitle(name); addWindowListener(this); } public void addLaunchButton() { setLayout(new GridLayout(1,1)); S_b = new Button("create new frame"); add(S_b); validate(); } public boolean action(Event event, Object arg) { if (event.target.equals(S_b)) { // odd that the number of Frame never decrease ? Frame ff[] = java.awt.Frame.getFrames(); System.out.println("java.awt.Frame.getFrames().length=="+ff.length); ff = null; System.out.println("action for b: " + event.toString()); XtoolkitIssue popup = new XtoolkitIssue("new sub frame",false); S_offset = S_offset + 50; System.out.println(S_offset); popup.setBounds(S_offset, S_offset, 250,100); popup.S_bigDummyData = new byte[1000*1000*5]; } return true; } public void windowOpened(WindowEvent we){ /* actually windowFirst-Opened would be a better name */ } public void windowClosed(WindowEvent we){ /* actually WindowDisposed would be a better name */ System.out.println("windowClosed (AKA WindowDisposed) " +we.getWindow()); // We could invoke the following, but they will not solve the leak // in sun.awt.X11.XToolkit // we.getWindow().removeWindowListener(this); // removeNotify(); // removeNotify(); // System.runFinalization(); } public void windowActivated(WindowEvent we){ } public void windowDeactivated(WindowEvent we){ } public void windowDeiconified(WindowEvent we){ } public void windowIconified(WindowEvent we){ } public void windowClosing(WindowEvent we){ System.out.println("windowClosing " +we.getWindow()); dispose(); if (S_etype == true) { // only the primary window invokes an application exits System.out.println("Application Exiting ..."); System.exit(0); } } public static void main(String args[]){ XtoolkitIssue Xtest = new XtoolkitIssue("main frame",true); Xtest.addLaunchButton(); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : A) focus/unfocus of another Frame, however this is not always possible, saying that a user will manipulate the GUI and eventually trigger that focus/unfocus to allow GC to complete is pretty lame, in fact it can result in a very unresponsive application as GC was deffered until a end-user manipulates a GUI. B) The work around is explicit <var>=null the S_bigDummyData varible at the time of the Frame.dispose() call which is pretty unacceptible, and a real anti-Java practice. For large applications this could be thosands of <var>=null statements.
|