Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6321941

GC failures via PhantomReference / WeakReference after Frame.dispose()

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 5.0
    • client-libs
    • x86
    • solaris_10

      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"


      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 arge complex applications (multi-window) that extend Frame/JFrame
      may not actually get correctly GC'd and thus cause memory exhustion releated to *)
      below e.g. a possible circular reference or code issue via PhantomReference and/or WeakReference, but this is beyond the scope of a simple test case which only highlights
      the *) condition.

      This issue only happens under Solaris 10 x86 with the XAWT e.g.
      setting -Dawt.toolkit=sun.awt.X11.XToolkit). It never happens under 1.4.2 or
      eariler JVMs.

      *) 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 leeds to a timiimg condition
         or race in which complex applications do not get fully garbage collected.

      May be related to 6257260, 6245243, 6240100 - the synopsys seems to support
      my claim in this bug report

           "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
      written by my company 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
      all memory in seconds, the work around is explicit <var>=null to hundreds of variables
      in eleven different classes [at least for this App] at the time of a 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
      1) Start Application (see source code below)
      2) Hit the "Create New Frame" button once
      3) Close the "popup Frame called "new sub frame"
      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.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      All HEAP associated with the Frame should free up
      ACTUAL -
      HEAP associated with the Frame frees up e.g. S_bigDummyData only on a focus/unfocus
      on another GUI Frame. However this behaviour will not work on complex HEAP structures, which are beyond the scope of a simple test case.

      Please note, if XToolkit is NOT used for 5.0 and 6.0 JVMs complex Heap allocation is indeed
      free'd up and also if a JVM of 1.4.2 or below is used complex Heap allocation is indeed
      free'd up on all Frame.dispose() calls. This is whay I assert that this is a timing issue in the
      GC sub-system due to

      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 C) 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"
      // 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) make sure that XToolkit is NOT used, however this
           results in horrible Fonts for Java AWT based applications
           due to Solaris 10 x86 screen DPI issues.

      B) Help the GC subsystem by doing explicit <var>=null
           to hundreds or thousands of variables i different
           classes at the time of a Frame.dispose() call. This wokrs
           but can take a day or two for every major Application and
           this seems pretty ANTI-java and thus is pretty unacceptible.

            dcherepanov Dmitry Cherepanov
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: