After writing the complete code the compiler compile the whole code at a time , but on the other hand interpreter take single line at a time. Both the compiler and interpreter are mostly called the language translator. how both are used in one language like in java.
In practice, there is no clear line between interpreters and compilers. Interpreters usually first compile the source code into some intermediate representation that is easier to interpret. Compiled machine code is also run by an interpreter: a CPU is just a hardware interpreter.
It is not true that an interpreter works line by line. That may have been true for BASIC interpreters, but isn't true for interpreters of more complex languages. Instead, the interpreter will use some intermediate representation or bytecode, and will then interpret one operation at a time. This does require that the entire source code of a file is parsed first.
Compilers don't necessarily compile everything up front. Just-in-time compilers (JIT) can compile small chunks of code on the fly, or can even patch existing machine code with an optimized version.
So there can be a lot of similarities between compilers and interpreters, and their exact boundaries are a bit fluid.
Java has a variety of implementations, some of them compilers, interpreters, or mixed forms. Java standardizes a bytecode format to which the source code is compiled up front. This is then used by interpreters/compilers.
- There are ahead of time Java compilers that turn all the bytecode into machine code. Modern Android uses such an approach. The HotSpot JVM does something like this in its server mode.
- There are pure Java interpreters. In the early days of Java this used to be more common. The HotSpot JVM can be run in an interpreted mode.
- But most of the time, a JVM will use a mixed interpreter/compiled mode.
The problem is that interpretation is very slow (often 10x–100x slower than compiled code). However, interpreters need to do fairly little work upfront so they can start fast. Compiled code runs much faster, but the compilation is CPU-intensive. So the runtime system will try to cheat:
- If code is only executed a few times, compiling it does not make sense. Let's start by interpreting the code.
- The interpreter keeps track of how often the code is executed.
- If a “hot spot” is detected, that code can be compiled in a background thread.
- The next time that code is executed, the compiled version will be used.
- The HotSpot JVM can't just switch to the compiled code the next time that function is called, it can also switch at the next loop iteration.
- Not all compiled code is equal: optimized code runs faster, but optimization takes time.
- This gives rise to tiered compilation: The compiled code is also instrumented, and very very hot code is recompiled with lots of optimizations.
- All of this means that Java applications typically start running slowly, and need some time to settle in while hot spots are detected and compiled.
Many JIT tricks rely on optimizations that make use of statistics that are only available at runtime. For example, they might notice that a function that takes an interface type as parameter is usually called with one concrete class. The JIT can then inline the methods of that class. This is a “speculative optimization” because it isn't correct – it's just assumed to be correct most of the time. These assumptions are tested with guard conditions. If they fail, the VM can switch back to an unoptimized version of the function. If they fail too often, the VM might deoptimize the compiled code. A related optimization is “inline caching”.