Search code examples
javacompilationjvmjitjvm-hotspot

why does java interpret code if it can compile it?


In Enterprise applications where the same code runs for days without ever getting restarted and if the code is hit multiple times i.e. more than the threshold time then it will be jit compiled anyway(most part of it) so i want to ask why it is not compiled in the first place.. i mean jvm engineers can compile the code to byte code to maintain platform independence and do one more compilation to machine code and shouldn't that machine code be faster in general case and when it meets the requirement of being jit compiled then jvm can enhance the machine code with all the profiling information and statistics and do all its enhancement. Surely that would take up the compilation time but general code instead of being interpreted every time is executed simply.i.e create a compiler which compiles and a boast up on it in case some method becomes hot. i might be wrong here but this is a curious question.


Solution

  • Compiling with optimizations is very expensive. Look at compile times of large C projects (e.g. firefox, linux kernel), especially with link time optimization.

    The JITs also compile for the target platform, i.e. they try to compile with all available instructions that they can support, which means you cannot distribute compiled code.

    Now consider that the JITs perform speculative optimizations (based on profiling) which may turn out wrong and need to bail out. If only compiling were an option this code would not be able to continue to run until it is recompiled. With an interpreter it can continue executing the uncommon code path that caused the bailout.

    You also have to keep in mind that some optimizations are workload-specific, i.e. a (bad) test workload might exercise different code paths than the real workload, and thus benefit from being compiled differently after it has been profiled at runtime.

    And not all applications are long-running daemons. Some things spin up JVMs to execute a single task which then exits when it is done.

    Also consider that a lot of code only runs once, e.g. during application startup or shutdown.

    All these factors contribute to why some JVMs use a combination interpreters + compilers by default. Others may only use AOT-compiled code or only use an interpreter due to different technical tradeoffs, but they're generally not faster.