Is CLR a virtual machine?

I read a book that referenced the .net CLR as a virtual machine ? Can anyone justify this? What is the reason we need the concept of virtual machines on some development platforms?

Is it impossible to create an embedded infrastructure (without a virtual machine) that is fully object oriented and as powerful as .net?

In a book that refers to the CLR as a virtual machine, " Professional.Net Framework 2.0 ."

+42
clr vm-implementation
Oct 14 '09 at 5:13
source share
7 answers

There are many misconceptions. I suppose you could think of .Net as a virtual machine if you want, but see how the .NET Framework really handles your code. A typical scenario is as follows

  • You are writing a .Net program in C #, VB.Net, F #, or in another compatible language.
  • This code is compiled to an intermediate language (IL), which is similar to Java bytecode that is distributed to end-user computers.
  • The end user first runs the program on a computer with the correct version of .Net installed
  • The computer sees that it is a .Net assembly, not a raw machine code, and passes it to the JIT compiler
  • The JIT compiler compiles IL into completely native machine code.
  • Native code is stored in memory for the entire duration of this program.
  • The stored code is called, and IL no longer matters.

There are a couple of important points here, but the big one is that in no case is any code ever interpreted. Instead, in step 5, you can see that it is compiled into native code. This is a huge difference than downloading it to a virtual machine for several reasons:

  • Fully compiled code is executed directly by the processor, and is not interpreted or translated using an additional layer of software abstraction, which should be faster.
  • The JIT compiler can take advantage of the optimization benefits of a particular machine running the program, rather than determining the lowest common denominator.
  • If you want, you can even precompile the code and essentially completely hide step 5 from the user.

I suppose you could call it a virtual machine, in the sense that JITter abstracts the details of the real machine from the developer. Personally, I don’t think that this is true, because for many people a virtual machine involves abstraction of runtime from its own code, which simply does not exist for .Net programs.

Another key point about this whole process that really sets it apart from the “virtual machine” environment is that it is just a typical process. If you really want to, you can precompile the .Net assembly before distribution and deploy your own code directly to end users (hint: it is slower in the aggregate over the entire life of the program because you lose optimization for a particular machine). Of course, you still need the installed .Net environment, but at the moment it really is not much different from any other runtime API; it looks more like a dll collection with a good API that you can reference with, as it may be due to the runtime of VB or C. Microsoft also ships with Visual Studio. This view takes IL from a photograph, making the VM nickname much harder to justify. (I say “view” because IL is still deployed and used to validate stored code, but it never touched it to execute).

Another important point is the lack of a virtual machine process. When the application starts, there is no ordinary sandbox process. Compare this to Java, where if you open the task manager when the program starts, you will see a process specifically designed for the Java virtual machine, and the actual application process is a thread inside the sandbox created by the virtual machine. In .Net, you see the application process directly in the Windows task manager.

In short: you could say that IL + CLR + JIT together somehow make up a virtual machine. Personally, I do not think so, but I will not argue with you if you believe this. What I want to do is that when you tell someone that .Net is running on a virtual machine without any further explanation, the idea that you are communicating with this person is an "interpreted bytecode to the host process. " And this is simply wrong.

+75
Oct 26 '09 at 14:19
source share

Like the Java Virtual Machine (JVM),. Net CLR is a virtual machine that interprets byte code.

The JVM interprets programs that contain java byte codes, and the .net CLR interprets programs that contain what Microsoft calls Intermediate Language (IL) instructions. There are differences between these byte codes, but virtual machines are similar and strive to provide similar functions.

Both of these versions of the virtual machine have the ability to compile their input bytecode into the machine language of the computer on which they are running. This is called "Just In Time Compilation (JIT)," and the resulting output code is called the "JIT Code." Because the JIT code contains sequences of instructions in machine language of the computer CPU, this code is sometimes called the "native" code.

However, the JIT code is qualitatively and quantitatively different from the code based, as explained below. For this reason, in this article, JIT code is nothing more than a built-in implementation of a virtual machine when a specific bytecode program is run.

One of the possibilities that both of these virtual machines (VMs) are striving to provide is security in the form of preventing some dangerous programming errors. For example, the title of this web forum, stackoverflow, is inspired by one of these dangerous bugs that is possible in native code.

To ensure security and runtime security, virtual machines implement type safety at the Virtual Machine level. VM memory assignments are needed to store the type of data that is stored in this memory location. For example, if an integer is pushed onto the stack, it is not possible to pop a double from the stack. C-style "unions" are prohibited. Pointers and direct memory access are prohibited.

We could not get the same benefits using an object-oriented language environment for developers, if the result is a native binary, such as an EXE file. In this case, we will not be able to distinguish between source binaries generated using the framework and EXE created by an attacker using sources other than the structure.

In the case of virtual machines, type security is applied at the "lowest level" to which the programmer is allowed access. (Neglecting for a moment that you can write managed native code, that is.) Therefore, no user will encounter an application that performs one of the dangerous operations that require direct access to memory cells and pointers.

In practice, CLR.NET implements a way to write its own code, which can be invoked by "managed" .net code. In this case, the burden lies with the author of his own code so as not to make pointer and memory errors.

Since both the JVM and the .net CLR perform JIT compilation, either the virtual machine actually creates binary code with source code from the supplied bytecode. This "JIT code" runs faster than the execution of the virtual machine interpreter, because even the machine language code generated by the JIT contains all the necessary VM security checks that the VM will execute. As a result, JIT output code is not as fast as native code, which usually does not contain numerous runtime checks. However, this lack of speed performance is being replaced by improved reliability, including safety; in particular, the use of uninitialized storage is prevented, destination type security is maintained, the range is checked (thus preventing buffer and heap overflows), the lifetime of objects is controlled by garbage collection, and dynamic allocation is safe by type. The environment that performs such runtime checks implements the specification of the virtual machine and is slightly larger than the implementation of the machine language of the virtual machine.

+21
Oct. 14 '09 at 5:25
source share

The "Virtual Machine" part refers to the fact that .NET code is compiled into EXE and DLL as an "intermediate" assembly language (IL) to run on a virtual machine, unlike the actual processor assembly language. Then, at run time, ILM is converted to the actual processor assembly for execution (called "just in time" or JIT compilation).

Of course, you could write a .NET compiler so that it is compiled in processor assembly language instead of IL. However, this would not be portable for all processors - you will have to compile a different version for each OS / CPU pair. But by compiling in ILM, you allow the "virtual machine" to process things specific to the processor and OS.

+6
Oct 14 '09 at 5:20
source share

The advantage of the CLR is the freedom to write code in any programming language that the developer chooses, since the code will be compiled to the CLR before being interpreted in native calls. The .NET framework uses this JIT compilation to handle all the uniformly and output programs that work for deployed a platform that is missing in compiled languages.

+2
Oct 14 '09 at 5:21
source share

I'm a little old school, so I call the CLR a virtual machine. My reasoning is that the CLR collects machine code from intermediate bytecode, which is what a virtual machine does.

The benefits of the CLR are mainly related to the way it compiles machine code that uses information such as runtime.

You can create your own environment, as powerful as the .NET framework, using only native types. The only flexibility you lose is the ability to build your own code if you ever port your program to another platform without recompiling.

+2
Oct 14 '09 at 5:23
source share

Neither the JVM nor the CLR do anything substantial than what most "virtual machines" do for other languages. Currently, they all use JIT to convert virtual instructions (p-code, byte codes, intermediate language instructions, call them whatever you like) to instructions of the "built-in processor" ("machine code").

In fact, the first virtual machine to do this was the Smalltalk virtual machine. The author of this innovation, Peter Deutsch, called it "dynamic translation" instead of the term "JIT", which was popularized by Java. If the focus of execution of Smalltalk is called a "virtual machine" (and what it still calls), then any and every "runtime system" that essentially does the same will also qualify as "virtual machines." "

+2
Jul 03 '14 at 22:28
source share

You have a lot of valuable answers, but I think that has not yet been mentioned: modularity.

It is very difficult to export an OO class from a native DLL. Of course, you can tell the linker to export the class and import it somewhere else, but it's fragile; Changing one private member in a class will violate binary compatibility, i.e. If you change one DLL without recompiling all the other modules, your program will crash terribly at runtime.

There are several ways: for example, you can define public abstract interfaces, extract from them and export global factory functions from your DLL. This way you can change the implementation details of the class. But you cannot get this class in another DLL. And, of course, changing the interface also breaks binary compatibility.

I am not sure if there is a good solution for this in the native code: if the compiler / linker creates its own code at compile time, it should know the exact memory layout of the classes / structures that are used in the code. If the last compilation step (generating native code) is delayed until the method is called for the first time, this problem will simply disappear: you can change the class in the assembly and as long as the JIT can resolve all the members used at runtime, everything will work fine.

In a nutshell: if you are creating a monolithic, single-task program, perhaps you can have most of the powerful .NET features with a compiler that creates your own code. But the disadvantages of having a JIT compiler (installing the infrastructure, slightly longer startup periods) do not really outweigh the benefits in most cases.

+1
Oct 26 '09 at 15:06
source share



All Articles