Using finalizers to free up local resources

Source: Internet
Author: User
Tags finally block protected constructor terminates

We had a basic understanding of garbage collection and managed heap, including how to reclaim the memory of objects during the garbage collection period, and fortunately, most of the types will work as long as memory is available, but there are other types that use local resources in addition to memory.

For example, the System.IO.FileStream type needs to open a file (local resource) and save a handle to the file. Then, the Read and write methods of that type use the handle to manipulate the file, similar to the System.Threading.Mutex type that opens a Windows Mutex core object (local resource) and holds its handle, and uses the handle when calling the mutex method. Finalization (finalization) is a mechanism provided by the CLR that allows objects to perform some decent cleanup before garbage collection. Any type that contains local resources (such as files, network Connections, sockets, mutexes, and other types) must support finalizers. Simply put, the type implements a method named Finalize. The Finalize method of the object is called when the garbage collection period determines the garbage of an object. It can be understood that any type that implements the Finalize method is actually saying that all of its objects want to eat the last meal before being executed.

The C # Team believes that the Finalize method is a method that requires special syntax in a programming language. Therefore, in C #, you must define a finalize method with a ~ symbol before the class name, as shown in the following code:

public class SomeType

{

~sometype ()

{}

}

Compiling the appeal code and checking the resulting assembly in ILDasm.exe, you will find that the C # compiler actually generates a method named Finzlize in the metadata of the module.

Viewing the metadata for a method, you find that the Base.finalize () method of the base class is called in the finally block in a try {} finally{} code block. When implementing the Finalize method, it is common to call the CloseHandle function of Win 32 and pass the handle of the local resource to its function. For example: The FileStream type defines a file handle field that identifies the local resource. The FileStream type also defines the Finalize method, which internally calls the CloseHandle function and passes the file handle field to it. This ensures that the local file handle is closed after the managed FileStream object is identified as garbage. If the type that wraps the local resource does not have a Finalize method defined, the local resource cannot be closed, causing the resource to leak until the process terminates. These resources are reclaimed locally when the process terminates.

1. Use the CriticalFinalizerObject type to ensure termination

To simplify programming, a CriticalFinalizerObject class is defined in the System.Runtime.ConstrainedExecution namespace

Look at the class and discover that the class is nothing special, but the CLR treats the class and its derived classes in a special way. Specifically, the CLR gives this class the following three cool features.

1) When you first construct an object of any CriticalFinalizerObject derived class, the CLR immediately JIT-compiles all the finalize methods in the inheritance hierarchy. Compiling these methods when constructing an object ensures that the local resources are freed after the object is designated as garbage. If you do not compile the Finalize method ahead of time, you may be able to ensure that local resources are compiled and used, but there is no guarantee that these resources will be released. When memory is tight, the CLR may not find enough memory to compile the Finalize method, which prevents the execution of the Finzlize method, causing local resource leaks. In addition, if the code in the Finalize method references a type in another assembly, and the CLR fails to find the assembly, it can also cause resource leaks.

2) The CLR can call a finalize method of a CriticalFinalizerObject derived type after calling a finalize method of a non-criticalfinalizerobject derived type. In this way, managed resource classes can successfully access the objects of the CriticalFinalizerObject derived class in their Finalize method.

3) If an AppDomain is forcibly interrupted by a host application (such as SQL server,asp.net), the CLR invokes the Finalize method of the CriticalFinalizerObject derived type. This feature is also used to ensure that local resources are freed when the host application no longer trusts the managed heap code that runs inside it.

2.SafeHandle types and derived types

Now Microsoft realizes that the most common local resources are the resources that Windows provides. Also aware that most of the resources are manipulated with handles, the same for ease of programming and more secure, a SafeHandle class is defined in the System.Runtime.InteropServices namespace in the following form:

For the SafeHandle class, it focuses on two points. First, it derives the word CriticalFinalizerObject; This ensures that the CLR will be treated with special care. Second, he is an abstract class that must have a class derived from this class and override the get accessor method of the protected constructor, abstract method ReleaseHandle, and abstract property isinvalid.

In window, if the value of the handle is 0 or-1, then most of them are invalid, The namespace Microsoft.Win32.SafeHandles contains a Safehandlezeroorminusoneisinvalid helper class.

The same class is also an abstract class. There must be another class that derives the word from the class, and overrides the protected constructor and abstract method of the ReleaseHandle method. The. NET Framework provides only a few classes that derive from Safehandlezeroorminusoneisinvalid. These include Safefilehandle,saferegistryhandle,safewaithandle and SafeBuffer. The following is the Safefilehandle class

The implementation of Safewaithandle is the same as the implementation of Safefilehandle, the interior is called Win32native.closehandle (), the method of the same code, the implementation of different classes, is to ensure type safety The compiler does not want to pass a file handle as an argument to a wait handle method. The ReleaseHandle method of the Saferegistryhandle class calls the win RegCloseKey function.

The. NET Framework also provides additional classes to wrap local resources: Safeprocesshandle, Safethreadhandle,safetokenhandle,safefilemappinghandle, Safeviewoffilehandle,safelibraryhandle and Safelocalallochandle.

In fact, all of these libraries have been published in conjunction with the Framework Class Library (FCL). But these classes are not publicly available, they are all used inside MSCorLib.dll and System.dll, and Microsoft is not exposing these classes because they don't want to test them completely, and they don't want to spend time writing their documents. If you want to use these classes, you can use the Anti-compilation tool to extract the classes and put them into your own code.

3. Interacting with unmanaged code using the SafeHandle type

As mentioned before: SafeHandle derived classes are useful because they ensure that local resources are freed when garbage collection occurs. In addition to the discussed features, SafeHandle also offers two additional features. First, to interact with unmanaged code, in which case using the SafeHandle derived class will get special treatment from the CLR.

In the above code, the prototype of the Createeventbad method is to return a IntPtr, before the. NET FRAMEWORK 2.0, the SafeHandle class does not exist, so it has to use the IntPtr type to label the handle. The CLR team found that the code was not robust enough that a threadabortexcption could be thrown before the handle was assigned a handle variable after calling Createeventbad. While this rarely happens, it will cause a resource leak once it happens. The only way to close the event created by the method is to terminate the process.

Now, in the. NET FrameWork 2.0 and later versions, you can use SafeHandle to fix this potential resource leak problem, and note that the Createeventgood method's prototype is to return a safewaithandle, When calling the Createeventgood method, the CLR calls the Win32 createevent function. When CreateEvent returns to managed code, the CLR knows that Safewaithandle is derived from SafeHandle. Therefore, an instance of Safewaithandle is constructed automatically, and the handle value returned from CreateEvent is passed at construction time. The construction of the new Safewaithandle object and the assignment of the handle are made in unmanaged code. Could not be interrupted by a threadabortexcption. It is now impossible for managed code to divulge this local resource, and finally the Safewaithandle object is garbage collected, and its Finalize method is invoked to ensure that the resource is freed.

The last feature of the SafeHandle derived class is to prevent someone from exploiting a potential security vulnerability. Now, one of the problems is. One thread may try to use a local resource while another thread is releasing the resource. This can cause a handle to circulate a vulnerability. The SafeHandle class uses a reference count when it prevents this security risk method. Internally, SafeHandle defines a private field class to maintain a counter. Once a derived object of a SafeHandle is set to a valid handle, the counter is configured to 1, and each time a SafeHandle derived class object is passed as a parameter to a person's unmanaged method, the CLR automatically increments the counter. Similarly, when an unmanaged method returns managed code, the CLR automatically decrements the counter. Of course, the operation of the counter is done in a thread-safe way, how does this promote security? When a thread attempts to free a local resource wrapped in a SafeHandle object, the CLR actually knows that it cannot release the resource because the resource is being used by an unmanaged code. When unmanaged code returns, the counter is decremented to 0 before the resource can be freed.

Also note that there is a CriticalHandle class in the System.Runtime.InteropServices namespace that does not reference counter functionality, and the other aspects are the same as the SafeHandle class, and the class and derived classes are traded for performance by sacrificing security. The CriticalHandle class also has its own derived class,

There are criticalhandlezeroorminusoneisinvalid, Criticalhandleminusoneisinvalid, because Microsoft prefers to build a more secure system than a faster one, so these two derived classes are not available in the class library.

Using finalizers to free up local resources

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.