The Artima Developer Community
Sponsored Link

Java Answers Forum
Will objects that have circular references to each other be Garbage Collect

10 replies on 1 page. Most recent reply: Apr 8, 2002 2:48 PM by Thomas SMETS

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 10 replies on 1 page
Srinivas

Posts: 6
Nickname: sbitla
Registered: Mar, 2002

Will objects that have circular references to each other be Garbage Collect Posted: Mar 21, 2002 9:47 PM
Reply to this message Reply
Advertisement
Hi,

Will objects that have circular references to each other be Garbage Collected?


Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Will objects that have circular references to each other be Garbage Collect Posted: Mar 21, 2002 10:24 PM
Reply to this message Reply
Yup, as long as there are no other references to either object.

Srinivas

Posts: 6
Nickname: sbitla
Registered: Mar, 2002

Re: Will objects that have circular references to each other be Garbage Collect Posted: Mar 21, 2002 10:41 PM
Reply to this message Reply
Hi,
Say there are two objects A and B. A has a reference to B and B has a reference to A. Now, how does GC know that those two objects are unreachable? Cann't GC find that object A can be reached from B and in the same way B can be reached from A? If more objects are involved it makes even more complex. In this case, will GC garbage collect these objects(if yes, how?) or will it lead to memory leak?

thanks
Srinivas.

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Will objects that have circular references to each other be Garbage Collect Posted: Mar 21, 2002 11:12 PM
Reply to this message Reply
Bill has detailed descriptions of the garbage collection algorithms on this in his book, Inside the Java 2 Virtual Machine. Fortunately for you, he has published the garbage collection chapter on this web site too: http://www.artima.com/insidejvm/ed2/ch09GarbageCollection01.html

Basically, it boils down to the fact that if only A refers to be and only B refers to A, then there is no object on any current stack frame referring to either, so the GC knows they are unreferenced, or "floating." This is because the GC is not using a simple reference-counting mechanism, as some (like Python, for instance) GCs do. If it were doing simple reference counting, then the problem you speak of would occur.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 22, 2002 6:25 AM
Reply to this message Reply
You may also want to play with the Heap of Fish applet, which graphically demonstrates a mark and sweep garbage collected heap. I wrote this applet for my third JavaWorld article back in 1996, back when applets were cool:

http://www.artima.com/insidejvm/applets/HeapOfFish.html

Mohit Gupta

Posts: 15
Nickname: mohit
Registered: Mar, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 24, 2002 1:24 PM
Reply to this message Reply
Book written by Bill would help u a lot about this topic. i myself study this topic from there and no doubt it help me in enriching my knowledge about gc.

still about ur question, i can say, that gc always looks for unreachable objects ie which are not reachable from root by any means. so if two or more objects have reference to each other but not reachable from root then they will gc'd by gc due to their unreachable status from root.
for this status checking of objects, gc use some algo's about which u can read from the book above mentioned.

Srinivas

Posts: 6
Nickname: sbitla
Registered: Mar, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 24, 2002 11:56 PM
Reply to this message Reply
Thanks for your response. Now let me tell you the problem I faced. I have four classes called WsPanel, WsTable, WsNavigator and SysMain. WsPanel extends JPanel and contains WsTable and WsNavigator. WsTable extends JScrollPane and contains JTable. WsNavigator extends JPanel and contains JButtons. SysMain is a JApplet and contains a WsPanel. In any WsPanel that contains WsTable and WsNavigator, WsTable references WsNavigator and WsNavigator references WsTable thus forming a circular reference. In my application WsPanels get created dynamically with user interaction with the system and added to SysMain. When a new instance of WsPanel is added to SysMain the previous WsPanel object of SysMain becomes eligible for GC and thus WsTable and WsNavigator objects it contains. When this was the situation I found a memory leak i.e. after working for 30 minutes with the system, the system was running out of memory. I have overridden finalize() methods of WsTable and WsNavigator and found that it was not getting fired at all. So, I thought that it was because of circular references between WsTable and WsNavigator and as a fix to this I removed the circular references of WsTable and WsNavigator(set to null) of WsPanel object, SysMain contains currently, just before adding a new instance of WsPanel to SysMain. This fix worked out. Now even after working for two hours with the system it is not running out of memory. If GC garbage collects all unreachable objects, what could be the cause for the problem I faced. And how the fix worked out? I am using JDK1.2.2.

Mohit Gupta

Posts: 15
Nickname: mohit
Registered: Mar, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 26, 2002 3:56 PM
Reply to this message Reply
if two or more objects have circular references to each other and are not reachable from root, then there is no reason that they would not be gc'd. it is. ya as u have explained ur problem, their might be any flaw in ur coding, u should check whether ur wspanel gc'd or not, as this might be possible that due to any leak it would not gc'd as it is presently referenced by any object either sysmain or... that's why not gc'd after removal from sysmain. so check for its status after making it null from sysmain or after releasing its referece from sysmain.
not in a situation to tell u exact reason as m not able to see ur code so thus try urself..and if find any result, inform.

Srinivas

Posts: 6
Nickname: sbitla
Registered: Mar, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 29, 2002 10:12 PM
Reply to this message Reply
Thank you Mohit Gupta. You are correct. There is another object(SysProcessButton) that references WsPanel which inturn references WsTable and WsNavigator. When I am done with SysProcessButton object I set it to null and everything got gc'd.
Thanks.
Srinivas.

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Will objects that have circular references to each other be Garbage Col Posted: Mar 29, 2002 10:45 PM
Reply to this message Reply
This subject thread is like an object with a circular reference in a reference-counting garbage collector.

Thomas SMETS

Posts: 307
Nickname: tsmets
Registered: Apr, 2002

Re: Will objects that have circular references to each other be Garbage Collect Posted: Apr 8, 2002 2:48 PM
Reply to this message Reply
Yes but they could be referenced by an active Thread which itself is not referenced any more ... This entire chain of Object is not reachable anymore but is not yet ellegible for GC either as it's still referenced by an active Thread.
import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.spi.LoggingEvent;
 
/**
  * This class tends to show that the <code>finalize</code>r are effectively 
  * run, but no <code>finalize</code>r of the unreachable chains of 
  * <code>Object</code>s are GCed.
  * 
  * In its current state the program should not show anything in the console
  * 
  * <pre>    
  *       public class FinalizedClass
  *       {
  *         public Category log;
  *         
  *         public FinalizedClass ()
  *         {
  *           log = Category.getInstance(FinalizedClass.class);      
  *         }
  *         
  *         public void finalize()
  *         {
  *           log.warn("finalize() run");
  *         }
  *       }
  * </pre>      
  * 
  * The code has been successfully tested on the JDK's 1.2.2, 1.3, 1.4  
  * 
  * @author <a href="mailto:tsmets@lautre.net">Thomas SMETS</a>, 
  * this program can be copied as long as the name of the author is referenced.
  * @version 0.3 - final
  * 
  */
public class ThreadedExampleWithoutGC
  implements Runnable
{
  public Category log;
  public int i;
  
  public static final int SLEEP_TIME = 1000;
  public static final int SPAWN_EVERY = 10000;
  public static final int ARRAY_SIZE = 10000;
  
  ThreadedExampleWithoutGC (int i)
  {
    log = Category.getInstance(ThreadedExampleWithoutGC.class);
    this.i = i;
    log.info ("ThreadedExampleWithoutGC " + i + " created");
  }
    
  public void run()
  {    
    int j = 0;
    int k;
    FinalizedClass o[];
    while (true)
    {
      o = new FinalizedClass[ARRAY_SIZE];  // Allocate the space for the Object
      try 
      {
        log.info("Hi, I am " + i + " this is my " + j++ + "th loop");
        for (k = 0; k < ARRAY_SIZE; k++)         
          o[k] = new FinalizedClass();    // 
        
        Thread.sleep(SLEEP_TIME);
      }
      catch (Exception ex) 
      {
        log.warn("Ooops I got an exception", ex);
      }
      
      for (k = 0; k < ARRAY_SIZE; k++)       // Simply dereferences the Custom Object
        o[k] = null;      
    }
  }
  
/**
  * The provided implementation of the finalize method simply allow 
  * to put Logging statement in it !   
  */    
  public void finalize ()
  {
    log.warn ("Running the finalizer for ThreadedExampleWithoutGC number " + this.i);
  }  
  
  public static void main (String[] args)
    throws Exception
  {
     int i = 0;
     BasicConfigurator.resetConfiguration();
     BasicConfigurator.configure(new CustomConsoleAppender(Priority.WARN));
     System.runFinalization();
     Thread t =null;
     do             // This "infinite" do-loop will generate java.lang.OutOfMemoryError
     {              // The program is therefore bound to crash before some of 
        try         // the finalizer are run
        {
          t = new Thread(new ThreadedExampleWithoutGC(i++));
          t.start();
          Thread.sleep(SPAWN_EVERY);
          t = null; // To make sure that no reference to the active Thread still exist.
        } catch (Exception ex) 
        { // Just in case the System runs out of Memory
          System.out.print("Exception " + ex.getClass());
        }        
     } while (true);       
  } // End of main
  
  /**
    * This class is there simply to allow an <code>Object</code> finalization 
    * to be logged with its own <code>Level</code> and space of logging.
    */
  public class FinalizedClass
  {
    public Category log;
    
    public FinalizedClass ()
    {
      log = Category.getInstance(FinalizedClass.class);      
    }
    
    public void finalize()
    {
      log.info("finalize() run");
    }
  } // End of inner class FinalizedClass
  
  /**
    *
    * This class allows for a quickly <i>custom logging</i> to the Console.
    * Any statement above the <code>Priority</code> level passed as
    * argument ot the constructor will be given to the parent 
    * <code>ConsoleAppender</code> for Logging.
    * 
    * I took this approache as I am not used to <code>PropertyConfigurator</code>, 
    * yet.
    * 
    * (Inner) Class is <code>static</code> for simplicity's sake. 
    * 
    */
  static class CustomConsoleAppender 
    extends ConsoleAppender
  {     
    Priority LoggingPriority = null;
    
    CustomConsoleAppender(Priority aLoggingLevel)
    {
      LoggingPriority = aLoggingLevel;
    }
    
    public void doAppend(LoggingEvent aLoggingEvent) 
    {
      if (aLoggingEvent.level.isGreaterOrEqual(LoggingPriority))
        super.doAppend(aLoggingEvent);
      return;    
    }
  } // End of Inner class CustomConsoleAppender 
}   // End of Class

Program output should be

java.lang.OutOfMemoryError
<<no stack trace vailable>> java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>
java.lang.OutOfMemoryError
<<no stack trace available>>

Remark some statement have been removed for simplicity's sake.

Flat View: This topic has 10 replies on 1 page
Topic: Problem with Paging Previous Topic   Next Topic Topic: Java source code

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use