1.5 The .NET Common Language Runtime


The CLR provides several basic runtime services:

  • Class loading . A class loader loads the assembly into memory.

  • Assembly integrity check. In addition to IL codes, each .NET assembly [13] contains a manifest. The manifest contains a hash code of the assembly contents. A check is made to see if the assembly contents have been altered based on this hash code. The CLR refuses to run assemblies that have been altered . This is an additional layer of protection to prevent malicious and illegal alteration of assemblies after distribution.

    [13] In short, a .NET assembly consists of individual software components placed together in a logical group . An assembly can consist of a single class or multiple classes. Assemblies are basically IL codes compiled from any .NET language. Refer to Appendix F for a more detailed explanation.

    This feature is not found in Java. The only way one can prove that a piece of Java byte code (such as an applet) hasn't been tampered with is to sign it with a digital signature. Verification is performed using the corresponding public keys of the signer.

  • Security checking. .NET allows role-based security and code-based security. When dealing with role-based security, the application is limited to security restrictions placed on the Windows account which the process is using to run the application. With code-based security, certain security policies are laid out for a particular .NET application so that it cannot do more than it is supposed to do. The .NET application fails to run if the CLR determines that it has violated the security policy set out for this application.

  • Memory type safety checking . .NET codes are considered to be memory type safe if they ever only access memory in a way that the CLR can control. Hence a memory type safe application will never attempt to read or write to a memory address that does not belong to it. Java developers should be familiar with this concept, since Java is also a memory safe language.

  • JIT compilation . After passing the security and integrity checks, IL codes are compiled on-the-fly into native machine codes which the underlying operating system (Windows) can understand. The JIT compiler [14] works in very much the same way as most standard Java JIT compilers do.

    [14] A JIT compiler is also known as a JITer in .NET literature.

    Instead of compiling everything into native machine code first, the JIT compiler only compiles methods when they are first invoked. The compiled codes are then cached so that the next time the same method is invoked, the native codes for that method in the cache are executed directly.

    Generally , JIT compilation yields superior runtime performance compared to the compile-everything-once-then-start-running strategy for most programs.

  • Garbage collection (automatic memory management) . An important component of the CLR is the garbage collector. Like JVM's, the CLR garbage collector runs as a background thread and periodically sweeps through memory to detect and collect unreferenced objects. In .NET, you no longer have to manually deallocate memory for unwanted objects, [15] the CLR does it for you.

    [15] For those with a C/C++ background: C# no longer needs you to delete objects in the destructor. So one trump card that Java has been holding over C++ has been annulled in C# “ automatic garbage collection can help prevent some of those sneaky memory leaks. Be cautious here though “ like Java, if you keep creating new objects and keep them referenced, you can still get an OutOfMemoryError . Only objects that are no longer referenced are garbage collected.

    One difference between Java's garbage collector and the CLR's is that for the latter, it is possible to programmatically force a garbage collection sweep to occur. Calling System.gc() or Runtime.gc() in Java does not guarantee that a garbage collection sweep occurs. The invocation simply informs the Java garbage collector that the Java program would like to perform a garbage collection. According to the JVM specification, the Java garbage collector has absolute discretion as to whether it wants to perform a collection sweep or not.

    For the CLR, calling System.GC.Collect() will force a collection sweep. Hence, although we can say that both garbage collection mechanisms are non-deterministic , [16] there is a bit more control over the process in .NET than in Java.

    [16] Meaning that our programs cannot determine when the next garbage collection sweep will occur.

Another way to look at the CLR is as a 'buffer layer' between the Win32 API [17] and your IL codes (see Figure 1.2). Instead of directly calling these Win32 API functions, .NET applications use classes and methods of the .NET BCL (this will be introduced in section 1.7.3) to invoke operating system services.

[17] The Win32 API is a set of functions provided by Microsoft for accessing operating system services. Because the Windows source codes are kept secret, Windows application developers can only interact with the Windows operating system through this set of API functions.

Figure 1.2. Services provided by the CLR are similar to those provided by the JVM.

graphics/01fig02.gif

There are differences between how Java runs byte codes on a JVM compared to how .NET runs IL codes in the CLR.

Java is fundamentally an interpreted language. [18] , [19] An interpreted language relies on a runtime interpreter which deciphers the codes (in Java's case, byte codes) for the local operating system during execution. Interpreted languages generally perform worse than compiled languages because interpretation can be an expensive process. Every time a method is invoked, the interpretation process kicks in regardless of how many times the same method has been invoked. In the case of compiled languages, the source codes are all compiled into native machine codes. During runtime, the machine codes are executed directly “ there isn't an additional layer of runtime interpretation by a runtime engine.

[18] Other interpreted languages include BASIC, LISP, and SmallTalk. C and C++ are compiled languages.

[19] There are (expensive) tools called native compilers which can convert all the byte codes into native machine-specific codes. Such precompiled codes do not need a JVM during execution, and generally perform better (depending on how good the native compiler is), but are no longer portable. Examples of such tools include Jove (www. instantiations .com), TowerJ (www.towerj.com), and Excelsior JET (www.excelsior-usa.com).

IL differs from Java here. IL is not interpreted but compiled on-the-fly into native machine codes by the .NET runtime. When a particular method coded in IL is invoked, the JIT compiler kicks in, converts the method from IL into native machine codes, and stores them in a cache. The next time the same method is invoked, the native codes from the cache are retrieved instead.

In performance, .NET on-the-fly compilation does have an advantage over traditional Java on-the-fly interpretation. However, it must be noted that most modern JVMs are implemented with a JIT compiler too (although this is not required). Most Java runtime engines today adopt the same JIT compilation model that .NET is running on. [20] Some JIT-based JVMs even allow you to turn the JIT feature on or off.

[20] A good example of a very efficient Java JIT compiler is Sun's Hotspot Java technology engine incorporated into JRE 1.3 and beyond. Besides on-the-fly JIT compilation of byte codes into native codes, Hotspot uses heuristics to determine which parts of a program need to be optimized for better performance. This adaptive optimization is achieved mainly via code inlining.

Theoretically, IL can be decompiled back into easy-to-understand source codes of any language [21] in very much the same way Java byte codes can be reversed back into Java source codes using a Java decompiler tool.

[21] No such tool exists at the time of writing, but I am pretty sure such tools will surface soon.



From Java to C#. A Developers Guide
From Java to C#: A Developers Guide
ISBN: 0321136225
EAN: 2147483647
Year: 2003
Pages: 221
Authors: Heng Ngee Mok

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net