Why compiling into intermediate code?

2019-04-29 11:12发布

问题:

Why do Actionscript, Java, C#, etc. compile into intermediate code? I'm aware of cross-platform benefits of using intermediate code.

The question is: What is the benefit of compiling to intermediate code, compared to scripts (JS, Python, PHP, Perl, etc.) that are interpreted?

Is it just for code obfuscation? Or what?

In addition what is the benefit compared to compiling to native code?

回答1:

First of all historically java was targeted to mobiles and embedded devices with very limited CPU/memory, and JVM on such devices can't do any intensive optimization, like modern JITs do for now. So java engeneers decided to move optimization to compile phase.

Next, having "byte code"/IL allows you to have many compilers from different languages into such byte code - and only one JVM/JIT. It is much more efficient then to create separate VM+JIT for each language. Remember, you have Java, JRuby, JPython, Groovy, etc... in JVM world, and C#, VB#, ASP.NET, F#, etc -- in .NET world, and only one runtime/VM for each.



回答2:

It is much faster to parse and JIT-compile IL code than to parse a high-level language like Java or especially C# (which has more features).

It also allows developers to use new language features without updating anything on the end-users' machines. (eg, LINQBridge)



回答3:

Intermediate code is very similar to assembly in that it contains a limited set of instructions. The runtime is then able to reliably and consistently operate on this (somewhat) small set of instructions without having to worry about parsing the language, etc. It can therefore gain performance improvements and make optimizations.



回答4:

In .NET compilation to MSIL solves interoperability between different languages like C#, VB.NET etc.



回答5:

Binary code instructions are very simple and atomic, much more so than programming statements can be.

For example, z = a + b - (c * d) would need to be translated into loading four values into registers, then an add, multiply, and subtract, then write into another memory location. So we have at least 8 instructions or so just for that line!

Intermediate code is the best of both worlds-- cross-platform, but also closer to the way machine code is normally written.



回答6:

In addition to SLaks's answer, compiling to IL enables a degree of cross-language interoperability that generally doesn't exist in interpreted languages.

This advantage can be huge for new languages. Scala's only been around since 2003, and it's already gained an immense amount of traction. Ruby, on the other hand, hasn't spread very far beyond being used for Rails apps in its 1.5 decades of existence. This is at least in part because Scala is bytecode-compatible with all pre-existing Java code and libraries, which gives it a huge leg up: Its community can focus most of its effort on the language itself, and potential adopters don't have to worry about going through any special contortions (or, worse yet, replacing their entire codebase) in order to start using Scala. F#'s story is almost identical, but for the other major managed environment.

Meanwhile Ruby doesn't speak with code from other languages quite so easily, so its community has to sink a lot more effort into developing Ruby-specific libraries and frameworks, and its potential users have to be a lot more willing to commit to a large-scale platform shift in order to use it.