Exploring the CLR
Total Page:16
File Type:pdf, Size:1020Kb
ch03.fm Page 89 Friday, December 6, 2002 3:49 PM THREE 3 Exploring the CLR In this chapter, I dig a little deeper into the CLR. In the .NET overview in Chapter 1, I briefly discussed metadata, MSIL, CTS, CLS, VOS, and VES. In this chapter, I dive deeper into all of these concepts. You will also understand what an assembly is and how the CLR locates assemblies, executes managed code, and enforces security. You’ll learn how the CLR implements automatic memory management (garbage collection) and what changes you need to make to your programming style to take advantage of it. As I go through this material, keep in mind that, just as you didn’t have to understand all the low- level details of the Win32 API to program on the Windows platform, you don’t have to be an expert on the CLR to use .NET. Understanding how the CLR works will make you a better programmer though, and this knowledge will help you to be a true .NET expert. Describing The CLR The CLR is an execution environment that loads and executes code. All Win32 operating systems (and indeed all other operating systems) have facilities to load and run binary files. However, no operating systems that I know of have a mechanism for verifying that the code they are running has not been tam- pered with or that the code does not violate type safety or access memory that it should not. This sort of security checking is particularly necessary in the Internet era when executable code may be received as an attachment to an email or downloaded automatically from a Web site. It’s also not usually the goal of most operating systems to make it easy for people to port software written for one operating system to other operating systems. Moreover, most 89 ch03.fm Page 90 Friday, December 6, 2002 3:49 PM 90 Chapter 3 G Exploring the CLR operating systems don’t provide system-level support for features desired by today’s software developers (garbage collection, stack walking, metadata, pro- gramming language independence, and so forth). Some programming lan- guages, like VB, provide support for some of these features in their language- specific runtimes. However, no operating system currently provides all of these features at the system level so that the features are available to any pro- gramming language that targets that operating system. Also, few operating systems have features specifically designed to make it easy to deploy and ver- sion software. DLL hell was becoming a sad fact of life with Windows applica- tions and a huge waste of time. Enhanced security, portability, and ease of development and deployment are just some of the goals of the CLR. The CLR is system-level code that subsumes some of the functionality of a traditional compiler (because it compiles MSIL code into native code). It also subsumes some of the functionality of the code loader in the operating system (because it reads PE format binary files and loads them into memory), and of language runtimes like the C runtime or the VB runtime (because it manages heap memory and provides services that make it easier to write soft- ware). The CLR is implemented as a set of DLLs. The most important of these is the runtime execution engine. The runtime execution engine is the part of the CLR that executes code; it can be found in a DLL called mscoree.dll that resides in your System32 directory. Other files required by the runtime, such as the file that contains the core pieces of the class library, mscorlib.dll, can be found in a directory called WINNT\Microsoft.NET\Frame- work\v1.0.3705. Your version number may vary. The binary files for the CLR are installed when you install the .NET Framework SDK or Visual Studio .NET. You will have to redistribute these files when you deploy a .NET Framework application. Microsoft provides a merge module that you can add to your setup to simplify this. With Microsoft’s newer operating systems, like Win- dows .NET Server, these files will be bundled with the operating system. However, even if the target platform has the .NET Framework installed, you may still need to distribute the specific version of the Framework that you built your application with. ch03.fm Page 91 Friday, December 6, 2002 3:49 PM Defining Managed Code and Managed Data 91 Defining Managed Code and Managed Data Code that runs under the control of the CLR is called managed code. By tar- geting the CLR, managed code enjoys all the benefits that I discussed in the previous section, enhanced security, portability, and so forth. The Official Definition of Managed Code The “official” definition of managed code from Partition 1 (Architecture) of the Tool Devel- opers Guide in the .NET Framework SDK Documentation is as follows: Managed code is simply code that provides enough information to allow the CLR to pro- vide a set of core services, including: G Given an address inside the code for a method, locate the metadata describing the method G Walk the stack G Handle exceptions G Store and retrieve security information You can find the Tool Developer’s Guide at: [Visual Studio .NET Install Directory]\ Frame- workSDK\Tool Developers Guide\docs. On my machine, the full path is: C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Tool Developers Guide\docs. Only managed code can access managed data. Managed data is a spe- cial memory heap that is allocated and released automatically by the CLR through a process called garbage collection. You can still create unmanaged code (which is the new name for the standard Win32 code you wrote before .NET) with Visual Studio .NET by cre- ating an MFC or Active Template Library (ATL) project in the latest version of Visual C++, which is included with Visual Studio .NET. Note You can also create managed code with Visual C++ thanks to something called C++ with Managed Extensions. There is also talk that Microsoft will support VB 6.0 for some time to come. Because the .NET Framework represents such a fundamental shift from Win32/ COM, the two platforms will likely coexist for a number of years. Unmanaged code cannot use managed data, and it will not enjoy the benefits afforded by the CLR: garbage collection, enhanced security, simpli- fied deployment, rich debugging support, consistent error handling, language independence, and even the possibility of running on different platforms. I will begin our tour of the CLR by looking at types. I then talk about assemblies. In the section on assemblies, you build a multifile assembly that we will use as a running example to illustrate other concepts throughout the ch03.fm Page 92 Friday, December 6, 2002 3:49 PM 92 Chapter 3 G Exploring the CLR chapter. After I talk about assemblies at a conceptual level, I discuss the two major constituents of an assembly: metadata and MSIL. I next discuss how the CLR locates assemblies. I end the chapter by discussing garbage collection and code access security. Types The .NET Framework is built around types. A type in .NET is a class, structure, interface, enumeration, or delegate. Every piece of code that you write in .NET, even the main program for your application, must be a member of some type. The following code shows the simplest “hello world” application that you can write. class TestClass { static void Main(string[] args) { System.Console.WriteLine("Hello World"); } } Notice that the Main method in this case is a static member of a class called TestClass. Not only will all of the code that you write be contained within some type, but all of the code that you use, both the classes in the .NET Framework base class library and any third-party class libraries, are all implemented as types. There are no global functions in .NET. What Is a Type? In the software world, a type is a just a set of operations, and, optionally, some state that all instances of that type have in common. Most programming languages have intrinsic types like the int, float, char, and long types in C/C++ (and C#) and the Integer, Single and String types in VB. Each of these types has some state representation associated with it. For instance, an int in C is either a 16- or 32-bit block of memory depending on the platform. A C float is a 32-bit block of memory on most platforms. Each of these types has a set of oper- ators that can be applied to them, and “+”, “-“, “/” are just a few of these operators. The main difference between these types is how they represent their state. The bits in a 32-bit int represent a base 2 number, and the bits in a 32-bit float represent a real number that is encoded using one of several formats, such as Institute of Electrical and Electronic Engineers (IEEE) 754. ch03.fm Page 93 Friday, December 6, 2002 3:49 PM Types 93 What Is a Type? (continued) Most programming languages also allow developers to create user-defined types that are conglomerates of the intrinsic types and other user-defined types, such as an Employee structure in C that contains an int ID member, a float salary member, and a string name member that is a null-terminated char array. Object-oriented programming languages intro- duced the notion of a class type that stores its state as a conglomerate of other types. Classes also support a set of methods that operate on the state; this is sometimes called the behavior of the class.