The end operation surface is very simple: Create an object, and when it is recycled, its Finalize method is called. But once deep research goes on, you'll find that the end operation is not so simple.
When an application creates a new object, the new operator allocates memory from the heap. If the type of the object defines a finalize method, a pointer to the object is placed in the finalization list before the instance constructor call of that type. The end list is an internal data structure that is controlled by the garbage collector. Each item in the list points to an object-his finalize method should be called before the memory of the object is reclaimed.
A heap that contains several objects. Some objects can be reached from the root of the application, and some are unreachable. When objects C, E, F, I, J are created, the system detects that the types of these objects define the Finalize method, so pointers to those objects are added to the Terminator list
Although System.Object defines a finalize method, the CLR knows to ignore it. That is, when an instance of a class is constructed, if the type's Finalize method continues from System.Object, the object is not considered to be terminated. The type must override the Finalize method of object, which is considered to be a finalizer of the class and derived types.
When garbage collection starts, objects B,e,g,h,i and J are judged as garbage. The garbage collector scans the list of endpoints to find pointers to these objects. When the pointer is found, the pointer is removed back from the endpoint and appended to the freachable queue, and freachable is another internal data structure for the garbage collection period. Each pointer in the Freachable queue indicates that its Finalize method is ready to call an object, which is the managed heap after the collection is finished.
The memory occupied by B,g,h has been reclaimed because they do not have a finalize method. However, the memory occupied by objects E,i and J is temporarily not recoverable because their finalize method has not yet been called.
A special high-priority CLR thread is specifically responsible for invoking the Finalize method. Use a dedicated thread to avoid potential thread synchronization problems. When freachable is empty (this is a common scenario), the thread will sleep. However, once an object appears in the queue, the thread is awakened, each item is removed from the freachable queue, and the Finalize method of each object is called. Because of the special way the thread works, the code in finalize should not make any assumptions about the thread that executes the code. For example, the local storage of a thread should not be accessed in the Finalize method.
The CLR may use multiple terminator threads in the future. Therefore, the code you write should not assume that the Finalize method is called consecutively. In other words, if the code in the Finalize method is exposed to the shared state, the thread synchronization lock should be used. In the case where there is only one finalizer thread, there may be multiple CPUs allocating the objects that can be terminated, but only one thread executes the Finalize method, which causes the thread to be able to keep up with the speed of the allocation, causing performance and scalability problems.
The interaction between the finalization list and finalize is very interesting. First, let me tell you the origin of this name for the freachable queue. F clearly represents the end (finalization); Each record entry in the freachable queue is a reference to an object in the managed heap that is called by the Finalize method of the object. Reachable means that it can be reached. In other words, the freachable queue can be seen as a root like a static field. Therefore, if an object is in freachable, it is accessible, not garbage.
Simply put, when an object is unreachable, the garbage collector treats it as garbage. However, when the garbage collector moves the object's reference from the Terminator list to the Freachable list, the object is no longer considered garbage and its memory cannot be reclaimed. When a Freachable object is tagged, objects referenced by the reference type of those objects are also recursively tagged, and all of these objects survive the garbage collection process until the garbage collector ends the garbage collection. Since some of the objects that were supposed to be garbage were thought to be not garbage, in a sense the objects were resurrected, and then the garbage collector began to compress the recoverable memory, and the special CLR thread emptied the freachable queue and executed the Finalize method for each object.
The next call to the garbage collection period will find that the object that has been terminated becomes a real garbage, because the root of the application no longer points to it, and the freachable queue no longer points to it. So the memory of these objects will be recycled directly. Objects that can be terminated throughout the process need to perform two garbage collections to free their memory, and in real-world applications, objects may be promoted to another generation, so more than two garbage collection may be required.
Section Sixth: End Operation decryption