I'm new to .Net and I'm trying to understand the basics first. What is the difference between MSIL and Java bytecode?
-
1Related question: http://stackoverflow.com/questions/453610/javas-virtual-machine-and-net-framework – Frank V Jan 17 '09 at 17:09
-
2A slightly more general comparison is at: http://stackoverflow.com/questions/682608/implementing-c-sharp-for-the-jvm – A R Jun 16 '12 at 01:10
8 Answers
First off let me say that I don't think that the subtle differences between Java bytecode and MSIL is something that should bother a novice .NET developer. They both serve the same purpose of defining an abstract target machine which is a layer above the physical machine being used in the end.
MSIL and Java bytecode are very similar, in fact there is was a tool called Grasshopper which translates MSIL to Java bytecode, I was part of the development team for Grasshopper so I can share a bit of my (faded) knowledge.
Please note that I stopped working on this around when .NET framework 2.0 came out so some of these things may not be true any more (if so please leave a comment and I'll correct it).
- .NET allows user defined types that have value semantics as apposed to the regular reference semantics (
struct
). - .NET supports unsigned types, this makes the instruction set a bit richer.
- Java includes the exception specification of methods in the bytecode. Although exception specification is usually only enforced by the compiler, it may be enforced by the JVM if a class loader other than the default one is used.
- .NET generics are expressed in IL while Java generics only use type erasure.
- .NET attributes have no equivalent in Java (is this still true?).
- .NET
enums
are not much more than wrappers around integer types while Javaenums
are pretty much fully fledged classes (thanks to Internet Friend for commenting). - .NET has
out
andref
parameters.
There are other language differences but most of them are not expressed at the byte code level, for example, if memory serves, Java's non-static
inner classes (which do not exist in .NET) are not a bytecode feature, the compiler generates an additional argument to the inner class's constructor and passes the outer object. The same is true for .NET lambda expressions.

- 110,860
- 49
- 189
- 262
-
1Regarding attributes - Java annotations can be set to appear in the bytecode as well, so there is an equivalent. – Oak May 31 '10 at 13:56
-
2@Oak: Java annotations only allow to pass data, while .NET attributes are fully powered classes, which may have logic and, most importantly, implement interfaces. – Fyodor Soikin Aug 28 '11 at 01:57
-
Bytecode also has separate return instructions for every kind of return type, dunno if it actually aids in type safety. – Cecil Dishwasher May 10 '13 at 18:55
-
2The fact that value types in .NET may sometimes be allocated on the stack is of trivial importance compared to the fact that they have *value semantics*; every value-type storage location *is* an instance. By contrast, every storage location in Java is either a primitive or a promiscuous object reference; there are no other types. – supercat Jul 23 '13 at 23:40
-
2Was wondering how they compare performance wise? Is MSIL faster to interpret then bytecode for eg? – Luke T O'Brien Oct 13 '17 at 14:26
CIL (the proper name for MSIL) and Java bytecode are more the same than they are different. There are some important differences though:
1) CIL was designed from the beginning to serve as a target for multiple languages. As such, it supports a much richer type system including signed and unsigned types, value types, pointers, properties, delegates, events, generics, an object-system with a single root, and more. CIL supports features not required for the initial CLR languages (C# and VB.NET) such as global functions and tail-call optimizations. In comparision, Java bytecode was designed as a target for the Java language and reflects many of the constraints found in Java itself. It would be a lot harder to write C or Scheme using Java bytecode.
2) CIL was designed to integrate easily into native libraries and unmanaged code
3) Java bytecode was designed to be either interpreted or compiled while CIL was designed assuming JIT compilation only. That said, the initial implementation of Mono used an interpreter instead of a JIT.
4) CIL was designed (and specified) to have a human readable and writable assembly language form that maps directly to the bytecode form. I believe that Java bytecode was (as the name implies) meant to be only machine readable. Of course, Java bytecode is relatively easily decompiled back to the original Java and, as shown below, it can also be "disassembled".
I should note that the JVM (most of them) is more highly optimized than the CLR (any of them). So, raw performance might be a reason to prefer targeting Java bytecode. This is an implementation detail though.
Some people say that the Java bytecode was designed to be multi-platform while CIL was designed to be Windows only. This is not the case. There are some "Windows"isms in the .NET framework but there are none in CIL.
As an example of point number 4) above, I wrote a toy Java to CIL compiler a while back. If you feed this compiler the following Java program:
class Factorial{
public static void main(String[] a){
System.out.println(new Fac().ComputeFac(10));
}
}
class Fac {
public int ComputeFac(int num){
int num_aux ;
if (num < 1)
num_aux = 1 ;
else
num_aux = num * (this.ComputeFac(num-1)) ;
return num_aux ;
}
}
my compiler will spit out the following CIL:
.assembly extern mscorlib { }
.assembly 'Factorial' { .ver 0:0:0:0 }
.class private auto ansi beforefieldinit Factorial extends [mscorlib]System.Object
{
.method public static default void main (string[] a) cil managed
{
.entrypoint
.maxstack 16
newobj instance void class Fac::'.ctor'()
ldc.i4 3
callvirt instance int32 class Fac::ComputeFac (int32)
call void class [mscorlib]System.Console::WriteLine(int32)
ret
}
}
.class private Fac extends [mscorlib]System.Object
{
.method public instance default void '.ctor' () cil managed
{
ldarg.0
call instance void object::'.ctor'()
ret
}
.method public int32 ComputeFac(int32 num) cil managed
{
.locals init ( int32 num_aux )
ldarg num
ldc.i4 1
clt
brfalse L1
ldc.i4 1
stloc num_aux
br L2
L1:
ldarg num
ldarg.0
ldarg num
ldc.i4 1
sub
callvirt instance int32 class Fac::ComputeFac (int32)
mul
stloc num_aux
L2:
ldloc num_aux
ret
}
}
This is a valid CIL program that can be fed into a CIL assembler like ilasm.exe
to create an executable. As you can see, CIL is a fully human readable and writable language. You can easily create valid CIL programs in any text editor.
You can also compile the Java program above with the javac
compiler and then run the resulting class files through the javap
"disassembler" to get the following:
class Factorial extends java.lang.Object{
Factorial();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3; //class Fac
6: dup
7: invokespecial #4; //Method Fac."<init>":()V
10: bipush 10
12: invokevirtual #5; //Method Fac.ComputeFac:(I)I
15: invokevirtual #6; //Method java/io/PrintStream.println:(I)V
18: return
}
class Fac extends java.lang.Object{
Fac();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public int ComputeFac(int);
Code:
0: iload_1
1: iconst_1
2: if_icmpge 10
5: iconst_1
6: istore_2
7: goto 20
10: iload_1
11: aload_0
12: iload_1
13: iconst_1
14: isub
15: invokevirtual #2; //Method ComputeFac:(I)I
18: imul
19: istore_2
20: iload_2
21: ireturn
}
The javap
output is not compilable (to my knowledge) but if you compare it to the CIL output above you can see that the two are very similar.

- 8,853
- 4
- 42
- 42
-
2It turns out there have been attempts to create a human readable/writable Java assembly language. Two that I have found are [Jasmin](http://jasmin.sourceforge.net/) and [Java Bytecode Assembler](http://tinf2.vub.ac.be/~dvermeir/courses/compilers/javaa/) – Justin Feb 20 '12 at 18:56
-
3I've written one here that's much better. Unlike Jasmin, it's designed to be able to disassemble and reassemble any valid classfile. https://github.com/Storyyeller/Krakatau. I think it'd be more accurate to say that Microsoft provides a standard assembler while Java coders have to make their own. – Antimony May 08 '13 at 17:43
They are essentially doing the same thing, MSIL is Microsoft's version of Java bytecode.
The main differences internally are:
- Bytecode was developed for both compilation and interpretation, while MSIL was developed explicitly for JIT compilation
- MSIL was developed to support multiple languages (C# and VB.NET, etc.) versus Bytecode being written for just Java, resulting in Bytecode being more similar to Java syntactically than IL is to any specific .NET language
- MSIL has more explicit delineation between value and reference types
A lot more information and a detailed comparison can be found in this article by K John Gough (postscript document)

- 31,890
- 5
- 57
- 86

- 21,603
- 7
- 53
- 64
-
"1.Bytecode was developed for both compilation and interpretation, while MSIL was developed explicitly for JIT compilation" - This talking about how Java code gets compiled down to bytecode AND that bytecode gets interpreted. Am I correct? Does MSIL not get interpreted to be executed? – Honinbo Shusaku Aug 16 '16 at 18:54
There are not that much differences. Both are intermediate formats of the code you wrote. When executed, the Virtual machines will execute the intermediate language managed that means that the Virtual Machine controls the variables and calls. There is even a language which I don't remeber right now that can run at .Net and Java the same way.
Basicly, it's just another format for the same thing
Edit: Found the language (besides Scala): It's FAN (http://www.fandev.org/), looks very interesting, but no time yet to evaluate

- 9,611
- 6
- 34
- 40
-
Scala can be compiled to target the JVM or the CLR, generating bytecode or MSIL respectively. – Daniel Spiewak Sep 18 '08 at 18:20
-
Good to know, but I found another language a month ago or so when reading DZone: Found it! See edit of my post – GHad Sep 18 '08 at 18:31
CIL aka MSIL is intended to be human-readable. Java bytecode is not.
Think of Java bytecode as being machine code for hardware that does not exist (but which JVMs emulate).
CIL is more like assembly language - one step from machine code, while still being human-readable.

- 40,215
- 13
- 94
- 127
-
1Bytecode is actually very readable as long as you have a hex editor. It's a pretty simple stack-based language with extensions for direct representation of classes and methods. I thought that MSIL was lower-level (e.g. registers)? – Daniel Spiewak Sep 18 '08 at 18:19
-
http://en.wikibooks.org/wiki/Transwiki:List_of_hello_world_programs#CIL http://en.wikibooks.org/wiki/Transwiki:List_of_hello_world_programs#Java_byte-code One is the *raw* CIL. The other is *disassembled* byte code. Bytecode may be reasonably readable if you grok hex, but that's not a design aim. – slim Sep 18 '08 at 18:25
-
"Disassembled" is really the wrong word for it. "De-encoded" maybe. Bytecode is unreadable in the .class files merely for compactness. Countrary to javap's man page, there's no disassembly involved in producing readable bytecode from a compiled class. – Daniel Spiewak Sep 18 '08 at 18:32
Serge Lidin authored a decent book on the details of MSIL: Expert .NET 2.0 IL Assembler. I also was able to pick up MSIL quickly by looking at simple methods using .NET Reflector and Ildasm (Tutorial).
The concepts between MSIL and Java bytecode are very similar.

- 1,413
- 15
- 21
I think MSIL should not compare to Java bytecode, but "the instruction that comprise the Java bytecodes".
There is no name of disassembled java bytecode. "Java Bytecode" should be an unofficial alias, as I cannot find its name in official document. The Java Class File Disassembler say
Prints out disassembled code, i.e., the instructions that comprise the Java bytecodes, for each of the methods in the class. These are documented in the Java Virtual Machine Specification.
Both "Java VM instructions" and "MSIL" are assembled into .NET bytecode and Java code, which are not human readable.

- 24,511
- 12
- 71
- 99
Agreed, the differences are minute enough to ingore as a beginner. If you want to learn .Net starting from the basics, I'd recommend looking at the Common Language Infrastructure, and the Common Type System.

- 1,082
- 7
- 10