站内搜索: 请输入搜索关键词
当前页面: 图书首页 > NET For Java Developers Migrating To C#

NET For Java Developers Migrating To C#

[ directory ] Previous Section Next Section

1.3 CLR and the JVM

Both .NET and Java use managed execution environments to run binary code. The two managed execution environments梩he .NET CLR and Java's JVM梐re quite similar in the role they play in running your code. Table 1.1 shows some of the similarities between the JVM and the CLR.

In Java, code is compiled to byte code, which is then run by the JVM. For better performance, the HotSpot JVM compiles commonly traversed parts of the byte code to native machine code. In .NET the source code is first compiled to MSIL and metadata, which is linked to form the assembly. The assembly can be an executable (EXE) file, a dynamic link library (DLL) file, or a module. At the time of execution, the MSIL and other pertinent information are sent to the class loader. The combined code is first sent to the verifier so that type safety can be checked, and then the just in time (JIT) compiler (JITer) compiles the MSIL to native managed code. .NET is different from Java because .NET code always compiles to native code.

Table 1.1. CLR versus JVM

CLR

JVM

Code management and execution environment for the .NET Framework

Code management and execution environment for the J2EE platform

Compiles application code to IL (Intermediate Language)

Compiles Java code to byte code

Does just in time (JIT) compilation; compiles IL to native code at the time of execution

Some JIT-based JVMs compile byte code to native code at the time of execution

Single unit of deployment (assembly)

Single unit of deployment (.jar files)

Automatic memory management through asynchronous garbage collection, automatic serialization, exception handling, code verification and security management, debugging, and profiling

Automatic memory management through asynchronous garbage collection, serialization, exception handling, a programmable and scriptable security model, debugging, and profiling

1.3.1 .NET MSIL

The MSIL is a set of CPU-independent instructions. The set includes instructions for loading, storing, initializing, and calling methods on objects, as well as instructions for arithmetic and logical operations, control flow, direct memory access, exception handling, and other operations. When a compiler produces MSIL, it also produces metadata. Metadata describes the types in your code, including the definition of each type, the signatures of each type's members, the members that your code references, and other data that the runtime uses at execution time. The MSIL and metadata are contained in a PE file that is based on and extends the published Microsoft PE and Common Object File Format (COFF) used historically for executable content. This file format, which accommodates MSIL or native code as well as metadata, enables the operating system to recognize CLR images. The presence of metadata in the file, along with the MSIL, enables your code to describe itself.

1.3.2 .NET JIT

The JIT compiler converts the MSIL into CPU-specific code that can then be executed. Rather than use time and memory to convert all the MSIL in a PE file into native code, it converts the MSIL as it is needed during execution and stores the resulting native code so that it is accessible for subsequent calls. The loader creates and attaches a stub to each of a type's methods when the type is loaded. On the initial call to the method, the stub passes control to the JIT compiler, which converts the MSIL for that method into native code and modifies the stub to direct execution to the location of the native code. Subsequent calls to the JIT-compiled method proceed directly to the native code that was previously generated, thereby reducing the time it takes to JIT-compile and execute the code.

Code must pass a verification process. Verification examines MSIL and metadata to find out whether the code can be determined to be type-safe, which means that it is known to access only the memory locations it is authorized to access. The runtime relies on the fact that the following statements are true for code that is verifiably type-safe:

  • A reference to a type is strictly compatible with the type being referenced.

  • Only appropriately defined operations are invoked on an object.

  • Identities are what they claim to be.

During verification, MSIL code is examined in an attempt to confirm that the code can access memory locations and call methods only through properly defined types. For example, code cannot allow an object's fields to be accessed in a manner that allows memory locations to be overrun. Additionally, verification inspects code to see whether the MSIL has been correctly generated, because incorrect MSIL could lead to a violation of the type-safety rules. The verification process passes a well-defined set of type-safe code, and it passes only code that is type-safe. However, some type-safe code might not pass verification because of limitations of the verification process, and some languages, by design, do not produce verifiably type-safe code. If type-safe code is required by security policy and if the code does not pass verification, an exception is thrown when the code is executed.

Chapter 2 discusses technical details of the MSIL and the JIT in action when you write your first C# program. But first let's discuss the equivalents of MSIL and JIT in the Java world. A first-glance comparison is that MSIL is equivalent to byte code in terms of what it does and what its responsibilities are. Also, the JIT compiler in Java has the same purpose as the JIT compiler in the CLR, although they have very different architectures. A thorough comparison between the Java byte code and MSIL and between the Java and CLR JIT compilers would not be very helpful without looking at a specific piece of code. Hence, that discussion is postponed until Chapter 2, which has many code examples.

1.3.3 The Java Virtual Machine

Using the javac compiler, the Java source code is compiled to byte code, which is also an assembly-like instruction set. Earlier versions of the Java Virtual Machine interpreted this byte code only at runtime, thereby giving true platform-independent execution. More recent versions of the Java runtime now compile sections of the byte code using the JIT compiler. The JVM then runs this native code.

Sun Microsystems' HotSpot compiler, the state of the art JIT compiler, profiles the execution of the byte code and identifies hotspots: pieces of code that get executed frequently and are performance-critical. By compiling only a small, critical portion of the byte code, the HotSpot compiler speeds startup time of execution, reduces memory consumption, and improves the overall user experience.

The Java language has some built-in optimization features that obviate the need for a full optimization of the byte code at compile time and at runtime. Most of the Java method calls are virtual (polymorphic) calls, and a frequent invocation of these methods can hurt performance; therefore, HotSpot in-lines the method call so that frequent method calls are faster. Because Java code can dynamically load and run classes, a full optimization of the byte code at compile time provides little benefit. HotSpot therefore does adaptive byte code compilation based on runtime profiling.

One of the key features of the .NET Framework and the Java environment that separates them from other traditional programming languages, such as C, C++, Fortran, and Pascal, is that these frameworks use a controlled execution environment to run the binary code. In contrast, traditional languages usually create libraries or executables that interact directly with the operating system. The .NET Framework provides the CLR, which provides basic infrastructure services for running binary code. The CLR is a piece of software that sits between your application code and the operating system. It takes care of many system-level details of process, memory, thread, type safety, and security management, thereby allowing you to concentrate on application code. We will explore some of these infrastructure services of the CLR.

    [ directory ] Previous Section Next Section