This discussion is archived
12 Replies Latest reply: May 28, 2013 6:18 AM by gimbal2 RSS

Garbage Collection

916903 Newbie
Currently Being Moderated
public class GarbageTest {
     private final Object helper;
     public GarbageTest(){
          helper = new Object();
          new TempObject(helper);
          //do other stuff for a long time
     }
     
     private static class TempObject{
          private final Object helper;
          public TempObject(Object helper){
               this.helper = helper;
          }
     }
}
I have a memory leak in my program, and I want to know is TempObject a candidate for garbage collection. Because all though I have no refrences to tempObject, tempObject has a reference to an object which will live as long the application is alive?
  • 1. Re: Garbage Collection
    Kayaman Guru
    Currently Being Moderated
    913900 wrote:
    I have a memory leak in my program
    Then use a profiler instead of guessing.
    and I want to know is TempObject a candidate for garbage collection.
    Yes, it falls out of scope at the end of the constructor. Of course your comment "do other stuff for a long time" looks weird, since you shouldn't be doing things for a long time in a constructor.
    Because all though I have no refrences to tempObject, tempObject has a reference to an object which will live as long the application is alive?
    But if that object doesn't reference TempObject, the GC is free to get rid of TempObject as it's not used by anything.
  • 2. Re: Garbage Collection
    916903 Newbie
    Currently Being Moderated
    Ive been trying to find the source of the leak using visual vm.

    Basically I have a jtabbedPane, I add a load of tabs, close them down, perform a full gc, and all the components should be gone, but I can see they are still in the heap.

    I do a heap dump, and then analyzed the references to objects which should have been cleared, but after ordersAndPricesPanel the refrenceTree seems to go out of my code, so Im not really sure how owns the references?

    I have pasted the screenshot below.

    [VisualVM screenshot|http://ctrlv.in/194304]
  • 3. Re: Garbage Collection
    Kayaman Guru
    Currently Being Moderated
    913900 wrote:
    Basically I have a jtabbedPane, I add a load of tabs, close them down, perform a full gc, and all the components should be gone, but I can see they are still in the heap.
    But do you have a memory leak? Just because you see something in the heap, doesn't mean that there's a memory leak. And if you're calling System.gc() yourself, you should know that it doesn't guarantee garbage collection.

    Do you actually run out of memory, or are you just being paranoid?
  • 4. Re: Garbage Collection
    916903 Newbie
    Currently Being Moderated
    Yes I know it performs a gc, as Im tailing the gc logs and can see that it does a full gc.

    There is deffiently a memory leak. It never actually runs out memory, but it goes into a loop of doing full gc's so often that the gui, becomes usuable because it is spending so long doing full gc's.
  • 5. Re: Garbage Collection
    Kayaman Guru
    Currently Being Moderated
    Well, are you disposing of the Swing components properly?
    I doubt that the lead cause would be something like what you proposed in your first post, since it's difficult to accidentally write code that would hang on to objects unnecessarily.
  • 6. Re: Garbage Collection
    gimbal2 Guru
    Currently Being Moderated
    Kayaman wrote:
    Well, are you disposing of the Swing components properly?
    Indeed. For example to properly clean up a JFrame/JDialog, you'd need to call dispose() on it. Simply making it invisible and nulling any reference to such an object still keeps it in memory since it is still registered internally in the Swing bookkeeping.
  • 7. Re: Garbage Collection
    916903 Newbie
    Currently Being Moderated
    public class GarbageTest {
         private static void main(String[] args){
              MainApplication app = new MainApplication();
              app.addTab("1", new SubPanel());
              app.addTab("2", new SubPanel());
              app.addTab("3", new SubPanel());
              app.addTab("4", new SubPanel());
              app.addTab("5", new SubPanel());
              
              for(int i = 0;i<5;i++){
                   app.removeTab(0);
              }
         }
    }
    
    class MainApplication{
         private final JTabbedPane tabbedPane;
         public MainApplication(){
              tabbedPane = new JTabbedPane();
         }
         public void addTab(String title, SubPanel subPanel ){
              tabbedPane.addTab(title, subPanel.getPanel());
         }
         public void removeTab(int index){
              tabbedPane.removeTabAt(index);
         }
    }
    
    class SubPanel{
         private final JDialog dialog;
         private final JPanel panel;
         private final JButton button;
         public SubPanel(){
              dialog = null;
              panel = new JPanel();
              button = new JButton("Show Dialog");
              init();
         }
         private void init(){
              button.addActionListener(new ActionListener(){
                   @Override
                   public void actionPerformed(ActionEvent e) {
                        dialog.setVisible(true);
                   }
              });
         }
         public JPanel getPanel() {
              return panel;
         }
    }
    My application is structures similiar to above. Now when I call subPanel.removeTab I expect that subPanel to be garbage collected. Are you saying that it wont be because the dialog has not been disposed?

    Thanks
  • 8. Re: Garbage Collection
    gimbal2 Guru
    Currently Being Moderated
    913900 wrote:
    Are you saying that it wont be because the dialog has not been disposed?
    No I did not say that at all.

    Is that code meant to be something that other people can run? Because it doesn't compile due to main() not being public and even when you fix that, the code doesn't actually initialize the dialog anywhere.
  • 9. Re: Garbage Collection
    ++sja Explorer
    Currently Being Moderated
    If I stick System.gc() at the end of main() in the test program and run it under hprof, I see no extraneous JPanel objects remaining in memory.

    Try this: make sure you have the latest JRE, in case there is a leak that has been fixed. Start your app with "java -agentlib:hprof". Play with your app for a while, then arrange it to call System.gc(); System.exit(0);. Search the resulting java.hprof.txt file for the percent sign, that's where you'll see columns "live bytes" and "live objs", those are where your memory is being used. Anything that seems to grow significantly if you play with the app longer before exiting? Google "java hprof" for instructions to e.g. make its stack traces longer, the default is often too short to see where something is being allocated.
  • 10. Re: Garbage Collection
    mKorbel Explorer
    Currently Being Moderated
    nothing from this code (public class GarbageTest { ....} ) can cause any type of memory lack, only bunch of exceptions

    1. there isn't JFrame, JDialog, JWindow, nor visible,

    - code created 5th JDialogs never vill be visible, initialized and null,
    - then dialog.setVisible(true); can created only exception
    - code isn't compilable, runnable, then everything here could be only speculations,
    - no idea why is created and removed 5empty tabs in JTabbedPane (empty == JPanel with JButton and with dead JDialog)
    - (my attampt) code created on Initial Thread consumed cca 8Mb, if EDT ended (all methods are executed, ETD is empty) used memory is finalized to 2Mb

    2. JFrame, JDialog, JWindow never will be GC'ed,

    - there isn't finalize() in API, can't be because Top-Level Container are created on peers came from Native OS,
    - these resorces are terminated with current JVM
    - by default there (for JVM used memory) isn't significant difference betweens dispose() and setVisible(), both methods returns used resources from 2D Graphics only
    - all those contianers are re_usable untill current JVM exists, Window[] returns all initialized Top-Level Containers,
    - Top-Level Container must return true from isDisplayable

    3. in the case you want to return allocated memory is required
    - create only one Top-Level Containers, re_use this container for another action
    - (wrong way) to call JFrame.getContentPane.removeAll(), there there stays empty container, removed contents will be CG'ed (non_static) in short time

    4. (as correctly mentioned) JProfiler returns all issues, returns list of allocaded memory v.s. methods/objectd
  • 11. Re: Garbage Collection
    916903 Newbie
    Currently Being Moderated
    Thanks for all your help, I finally found the issue:

    Each panel contained a JDateChooser, which registers a listener with a static class:
    MenuSelectionManager.defaultManager().addChangeListener(changeListener);
    http://grepcode.com/file/repo1.maven.org/maven2/com.luuuis/jcalendar-tz/1.3.3-3/com/toedter/calendar/JDateChooser.java

    Therefore allthough each panel was being removed from the tabbedPane, they were not gc'd because of this listener tie.

    Thanks again
  • 12. Re: Garbage Collection
    gimbal2 Guru
    Currently Being Moderated
    Congratulations on figuring it out! Please mark the thread as answered.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points