none
Gabage Collection and my classes RRS feed

  • Question

  • Folks
    if I write a class with one method that class has a base of System.Object. which has a Finalie protected method.
    When I use that class as an instance, does Gabage Collection place that object in the finalize queue, even though it never uses unmanaged code or large members?

    Also can anybody explain what happens to small objects that have a long life (5 mins) in the garbage collection process.


    regards

    GregJF
    Thursday, November 19, 2009 10:13 AM

Answers

  • The GC is smart enough to realize that the System.Object.Finalize is not a real method. So, your own class instances will not be placed on the finalize queue unless they have their own finalizer. The fact that they inherit from Object which has a finalizer is not enough to get on the finalize queue.

    Small objects are not GC'ed as long as they are reachable. Once they are no longer reachable (after 5 mins, in your example), they will become eligible for GC and get collected.

            -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Thursday, November 19, 2009 2:24 PM

All replies

  • The GC is smart enough to realize that the System.Object.Finalize is not a real method. So, your own class instances will not be placed on the finalize queue unless they have their own finalizer. The fact that they inherit from Object which has a finalizer is not enough to get on the finalize queue.

    Small objects are not GC'ed as long as they are reachable. Once they are no longer reachable (after 5 mins, in your example), they will become eligible for GC and get collected.

            -Steve


    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Thursday, November 19, 2009 2:24 PM
  • Maybe this is subtly off topic but I recommend that the class you are writing implement the IDisposable Interface and call GC.SuppressFinalize Method .

    In that link look at the example of how to use suppressfinalize and the IDisposable pattern for objects which don't implement a finalizer and by doing so guarentee that cleanup code is not called twice and depending on who calls it, the dispose, whether by the system or your code, it is handled properly and finalized does not come into play.

    GC.SuppressFinalize(this)

    Note only call the above method on your base object and not the objects which derive, they need to do their own dispose first and this call should be at the very end. HTH in an off topic way...


    William Wegerson (www.OmegaCoder.Com )
    Thursday, November 19, 2009 3:14 PM
    Moderator
  • Steve and OmegaMan

    Guys you seem to be saying two different things here:
    Steve you said:
    " class instances will not be placed on the finalize queue unless they have their own finalizer"
    OmegaMan you said:
    " use suppressfinalize and the IDisposable pattern for objects which don't implement a finalizer and by doing so guarentee that cleanup code is not called twice and depending on who calls it"
    So, do I need to use GC.SuppressFinalize(this) on my objects to avoid the queue (Omegaman) or do I not need to as the GC is smart enough AND the  fact that they  inherit from Object which has a finalizer is not enough to get on the finalize queue(Steve)?

    Which is it guys?


    Regards

    GregJF
    Thursday, November 19, 2009 10:24 PM
  • Steve is right and go with his.

    But I use that pattern on a majority of objects to which I clean up. You have to look at the individual situation and apply. But as suggested, Steve's is more in line currently with yours.
    William Wegerson (www.OmegaCoder.Com )
    Thursday, November 19, 2009 11:17 PM
    Moderator
  • Steve
    You that my own class will not be put on the finalizer queue unless it has is own finalizer (overide I assume)

    So why is there such hype about using IDisposable and GC.SuppressFinalize?
    People all over the web, like Omegaman, are suggesting that we should use Idisposable and a dispose method pattern. If fact in VB.net Microsoft's Visaul Studio generates the following pattern when a class implements IDisposable
    '/************************************************

    #Region

     

    " IDisposable Support "

     

    Private disposedValue As Boolean = False ' To detect redundant calls

     

    ' IDisposable

     

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)

     

    If Not Me.disposedValue Then

     

    If disposing Then

     

    ' TODO: free other state (managed objects).

     

    End If

     

    ' TODO: free your own state (unmanaged objects).

     

    ' TODO: set large fields to null.

     

    End If

     

    Me.disposedValue = True

     

    End Sub

     

    ' This code added by Visual Basic to correctly implement the disposable pattern.

     

    Public Sub Dispose() Implements IDisposable.Dispose

     

    ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.

    Dispose(

    True)

    GC.SuppressFinalize(

    Me)

     

    End Sub

    #End

     

    Region




    '*************************************************/
    Note the first TODO: comment that suggests that class wide state objects should be cleaned up here
    And the last TODO: which suggests that large fields shouls always be cleaned up
    Of course this pattern is calling GC.Suppressfinalize(ME)

    So my questons are:
    1.Do we need to ever use IDisposable and GC.Suppressfinalize(me/this) when we have no overriding finalizer  or  unmanaged code calls
    2. and if we still do then at what pointdoes the Garbage collector start putting my class on the finalizer queue

    Regards

    GregJF 
    Sunday, November 22, 2009 10:00 PM
  • I wrote an entry on my blog describing when to implement neither IDisposable/finalizer, when to implement just IDisposable, and when to implement both:
      http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html

    You do need to implement them in some situations; I'd say about 10% of classes only need IDisposable, 5% need both, and 85% do not need either. However, those numbers are based on my preferred type of OO design (many small utility classes; very few large "combining" classes).

    You also may want to check out the other IDisposable references on my blog:
      http://nitoprograms.blogspot.com/search/label/IDisposable%2FFinalizers

    Your second question has an easier answer. A class is placed on the finalize queue when it is no longer reachable (and it actually has a finalizer).

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Monday, November 23, 2009 2:58 AM
  • Steve
    I got all that and it is very good.
    Now what if I have a method that uses a database connection and then calls the dispose method on the database connection object eg
    public void updateDbTable(MyClassData data)
        {
               using SQLConnection cn = new SQLConnection(_CnnString))
               {
                 // do database update stuff

               } 
            }        
    does this class need to implement IDisposable or is it only for class scoped members?

    (I have good reasons for being picky about this)

    regards

    GregJF
    Tuesday, November 24, 2009 1:28 AM
  • No, you dont have to implement IDisposable to dispose of cn.

    3 reasons:
    1) you already safely dispose of cn, because using is implemented with a try/finally block and calls dispose in the finally clause.
    2) Even if you would implement a finalizer, what would you finalize? As cn is local variable, you couldn't dispose it.

    I hope this answers your question.


    Tuesday, November 24, 2009 10:01 AM
  • Edsger is correct; I just wanted to point out his number (2) should read "Even if you would implement Dispose, what would you dispose?"

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Tuesday, November 24, 2009 2:02 PM
  • Edsger
    Thanks for that.
    I did actually realise that the using statement would call the cn.dispose method.
    And this does answer my question(does this class need to implement IDisposable or is it only for class scoped members?): it is:it only for class scoped members

    I hope I am on the right track.

    Now my next question is, if I have a private "class scoped" member, say of the type XMLDocument, and one of my methods populates this member with 100kkbs of data.
    The member is use by other methods in the class.

    Do I need to implement IDisposable and set this member to nothing in the Dispose(true) method?

    Regards (and thanks for helping and being so patient)

    GregJF
    Tuesday, November 24, 2009 9:57 PM
  • Hello

    It seems that nobody in this thread mentioned this great article about Dispose and Finalize. I add it. :)
    http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae

    The article mentions a lot of Do / Do not implement IDisposable guidelines.

    GregJF

    You may have notice that XmlDocument is special. XmlDocument does not implement IDisposable. It has no Close or Dispose method because it is an in-memory representation of an XML document. Once read, the file is no-long needed.  According to Nito's article:

    There are only two situations when IDisposable does need to be implemented:
     The class owns unmanaged resources.
     The class owns managed (IDisposable) resources.


    It appears that your class does not need to implement IDisposable because it does not own unmanaged or managed (IDisposable) resources.

    If you set the XmlDocument object to null in Dispose, the large XmlDocument object is ready to be cleaned in the next GC.  I think that implementing IDisposable in this case is valuable only when you may need to hold a reference to the parent object for a relatively long time after you call Dispose on it.


    Regards,
    Jialiang Ge
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, November 25, 2009 6:15 AM
    Moderator

  • There are only two situations when IDisposable does need to be implemented:
     The class owns unmanaged resources.
     The class owns managed (IDisposable) resources.

    I would add:

    • The class subscribes to events.
    It is commonly overlooked but a memory leak can happen when a class does not unsubscribe (-=) to an event. Simply setting it to null is not enough. A subscrived event will keep an object alive just as having a direct reference to it.
    William Wegerson (www.OmegaCoder.Com)
    Wednesday, November 25, 2009 2:57 PM
    Moderator
  • Are you saying that every class that subscribes to events should implement IDisposable and unsubscribe?

    edit:
    After thinking about your comment, I think you mean that subscriptions to events are stored as function pointers to the subscribing object. But this is hardly a special case like unmanaged resources. Such a leak can just as easily occur with normal references to objects. If one is going to make IDispobable interfaces for events, someone is learning a 'trick' without understanding how events really work and that these language elements are nothing more than fields/classes underneath. Personally I think it is better that someone knows that an object is only collected by the GC if it has no links to a referable objects anymore (and no sooner), and that event subscriptions are simply links.


    Thursday, November 26, 2009 10:14 AM
  • OmegaCoder's comment reflects a growing trend.

    Traditionally, IDisposable and Finalizers have been used to clean up unmanaged resources, and that's how they're treated on my blog.

    More recently, IDisposable has also been used to implement "shutdown semantics", if a type needs to perform some kind of shutdown logic that depends on other managed objects. This kind of shutdown code cannot go into a Finalizer, but IDisposable provides a decent vehicle.

    In particular, events may be problematic. To expound on OmegaCoder's comment, consider the following scenario (which is common in some data-binding situations):
    - Class A exposes an event X.
    - Class B is interested in event X, so defines a normal handler function OnX.
    - An instance of B subscribes to A.X, passing B.OnX as the handler.
    - Later in the program, the B object is no longer needed, so all references to it are removed.
    The tricky part comes in how events are implemented: they're multicast delegates. So, when the instance of B subscribes to A.X and passes its own B.X, in order to pass the "this" pointer to B.X, a reference to that instance of B is stored in A.X. When the B object is no longer used, the reference to B persists inside A.X. This causes B to "leak", since it is never GC'ed yet there are no obvious references to it.


    There is one problem with the whole IDisposable shutdown approach: it's never enforced. When dealing with unmanaged resources, if the user of the code does not call Dispose, then the Finalizer acts as a fallback and will ensure the resource is released. However, there's never a guarantee that IDisposable.Dispose will ever be called.

    Even with this drawback, IDisposable is still the best vehicle to carry shutdown semantics. The new Rx extensions library (community wiki: http://rxwiki.wikidot.com/) attempts to treat events as first-class objects, and the "Subscribe" method actually returns an IDisposable object; to unsubscribe, the IDisposable object is disposed.

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    • Proposed as answer by Edsger Friday, November 27, 2009 8:38 AM
    • Unproposed as answer by GregJF Sunday, November 29, 2009 10:06 PM
    Thursday, November 26, 2009 1:47 PM
  • Ok folks thanks for all this.
    So now, I don't wish to end this conversation yet as it has clear up only a couple of questions I have about the the Garbage Collection process, namely:
    -The Garbage collector distingiushes between referenced and referencing objects and cleans up thos that are neither by deallocating memory and not putting thme on the Finalizer queue
    - Objects that reference other managed objects can avoid having the GC put them on the Finalizer queue by implementing IDisposable and disposing of class scoped members and calling GC.SuppressFinalizer
    - Objects that reference unmanaged code can use a finalizer to ensure that references to unmanaged code are cleaned up if they weren't done so by the client calling the implemented IDisposable method(Dispose).

    But here are the questions that I am not clear on (mine you, I have not yet finished reading Joe Duffy's article as posted by Jialiang Ge):
    - when does the GC promote an object from Generation 0 to Generation 1 to Generation 2
    - What affect does a class that has many static/shared methods and members(50+)  have on:
              - this promotion of objects
              - how many times is the GC process called and recalled.
    - What effect does an application with many classes(1000+) that each have many static/shared methods and members(50+)  on this whole process.
    - What is the effect on implementing the IDisposable interface on all classes as a design pattern(or is it an anti-pattern) regardless of whether they need it now or not, but may need it later.


    Thanks again folks

    GregJF


    Sunday, November 29, 2009 10:26 PM
  • Ok folks thanks for all this.
    So now, I don't wish to end this conversation yet as it has clear up only a couple of questions I have about the the Garbage Collection process, namely:
    -The Garbage collector distingiushes between referenced and referencing objects and cleans up thos that are neither by deallocating memory and not putting thme on the Finalizer queue
    - Objects that reference other managed objects can avoid having the GC put them on the Finalizer queue by implementing IDisposable and disposing of class scoped members and calling GC.SuppressFinalizer
    - Objects that reference unmanaged code can use a finalizer to ensure that references to unmanaged code are cleaned up if they weren't done so by the client calling the implemented IDisposable method(Dispose).
    It's customary in the forums to have one thread per question.

    But here are the questions that I am not clear on (mine you, I have not yet finished reading Joe Duffy's article as posted by Jialiang Ge):
    - when does the GC promote an object from Generation 0 to Generation 1 to Generation 2
    - What affect does a class that has many static/shared methods and members(50+)  have on:
              - this promotion of objects
              - how many times is the GC process called and recalled.
    - What effect does an application with many classes(1000+) that each have many static/shared methods and members(50+)  on this whole process.
    - What is the effect on implementing the IDisposable interface on all classes as a design pattern(or is it an anti-pattern) regardless of whether they need it now or not, but may need it later.
    1) Whenever an object survives a GC, it gets promoted a generation. This is an implementation detail, however, and subject to change. Your code shouldn't depend on it.
    2) To put it simply: long-lived objects live longer. The whole "generation level" is merely an optimization, so that the GC can work more efficiently. In fact, the compact framework doesn't use generations.
    3) Again, keeping it simple: whatever objects your application needs (i.e., keeps a reference to) are not GC'ed.
    And to answer an implied question: the GC is called only when necessary.

    The bottom line about the GC is: don't worry about it.

    4) Well, that one's more controversial. It's true that adding IDisposable is a breaking change, but its presence is the result of an implementation detail. It could be argued that every single public class should implement IDisposable. You'll have to make your own decision on this one.

           -Steve
    Programming blog: http://nitoprograms.blogspot.com/
      Including my TCP/IP .NET Sockets FAQ

    Microsoft Certified Professional Developer
    Monday, November 30, 2009 2:17 PM