1. Allocate memory for that type by calling the the new operator.
2. Initialize the memory to set the initial state of the resource and to make the resource usable. The type's instance constructor is responsible for setting this initial state.
3. Use the resource by accessing the type's members (repeating as necessary).
4. Tear down the state of a resource to clean up.
5. Free the memory. The garbage collector is solely responsible for this step.
But the garbage collector knows nothing about the resource represented by the type in memory, which means that a garbage collector can't know how to perform Step 4 in the preceding list. So how is step 4 performed... The developer writes this code in the Finalize, Dispose, and Close methods.
Step 4 can be skipped for managed resources for example String. But for a type that wraps a native resource such as a file, a database connection, a socket, a mutex, a bitmap, an icon, and so on, always requires the execution of some cleanup code when the object is about to have its memory reclaimed.
Garbage collection algorithm
1. Marking phase
The garbage collector marks all of the reachable objects.
2. Compaction phase
The garbage collector compacts the memory, squeezing out the holes left by the
unreachable objects.
But the GC is a generational collector. So in the marking phase, instead of marking the whole heap it just focusses on generation (or a portion of heap).
Finalization - Releasing Native Resources
Any type that wraps a native resource, such as a file, network connection, socket, mutex, or other type, must support finalization. Basically, the type implements a method named Finalize. When the garbage collector determines that an object is garbage, it calls the object's Finalize method (if it exists).
When an application creates a new object, the new operator allocates the memory from the heap. If the object's type defines a Finalize method, a pointer to the object is placed on the finalization list just before the type's instance constructor is called. The finalization list is an internal data structure controlled by the garbage collector. Each entry in the list points to an object that should be finalised.
A. First Pass
When a garbage collection occurs, objects B, E, G, H, I, and J are determined to be garbage. The garbage collector scans the finalization list looking for pointers to these objects. When a pointer is found, the pointer is removed from the finalization list and appended to the freachable queue which is another of the garbage collector's internal data structures. Each pointer in the freachable queue identifies an object that is ready to have its Finalize method called. After the collection, the managed heap looks like
A special high-priority CLR thread is dedicated to calling Finalize methods. Because of the way this thread works, you shouldn't execute any code in a Finalize method that makes any assumptions about the thread that's executing the code. So if an object is in the freachable queue, the object is reachable and is not garbage. Then when the garbage collector moves an object's reference from the finalization list to the freachable queue, the object is no longer considered garbage and its memory can't be reclaimed.
B. Second Pass
The next time the garbage collector is invoked, it will see that the finalized objects are truly garbage because the application's roots don't point to it and the freachable queue no longer points to it either. The memory for the object is simply reclaimed.
Questions
1. Why can't C# support destructors ?
The CLR doesn't support deterministic destruction, which makes it difficult for C# to
provide this mechanism.
No comments:
Post a Comment