3 ms·
The JVM compiles the bytecode into machine code, and it compiles the hotspots of an application into optimized native machine code. Java execution is split int
by flatline3 14y ago
The JVM compiles the bytecode into machine code, and it compiles the hotspots of an application into optimized native machine code.
Java execution is split into two pieces. First is the interpeter, which is used to execute bytecode prior to it being compiled. The second is the compiler, which implements runtime optimized compilation of hotspots into native machine code, including the ability to make assumptions regarding types and then uncompile hotspots if those assumptions prove false.
Before you say "ah ha, an interpeter!", it's also notable that the JVM's interpreter is not an interpeter in the traditional sense (ala Ruby). Rather, the JVM's interpreter is an architecture-specific interpreter that decodes JVM bytecode and spits out unoptimized direct machine code based on a standard set of machine code templates. This is fast, but there's not optimized compiler, and so it's not nearly as fast as the result of the optimizing compiler that is run over the hotspots.
All that said, JIT vs AOT is a technical decision with mixed advantages. In theory, there are optimizations that can only be performed via JIT, based on runtime analysis. The simplicity of AOT can often provide runtime performance gains simply by avoiding the runtime costs of evaluation and compilation. JIT of bytecode allows for binary/library portability across different machines without worrying about rebuilding or shipping multiple binaries. AOT is somewhat more difficult to decompile compared to unoptimized byte code.
Mono compiles down AOT for iOS, in theory you could do the same with Java. GCC did so with their optimizing AOT gcj Java compiler.