0
votes

I fail to understand the difference between an interpreter and JIT. For instance, from this answer:

JVM is Java Virtual Machine -- Runs/ Interprets/ translates Bytecode into Native Machine Code

JIT is Just In Time Compiler -- Compiles the given bytecode instruction sequence to machine code at runtime before executing it natively. It's main purpose is to do heavy optimizations in performance.

Both produce native machine code. Then, from this other answer:

An interpreter generates and executes machine code instructions on the fly for each instruction, regardless of whether it has previously been executed. A JIT caches the instructions that have been previously interpreted to machine code, and reuses those native machine code instructions.

As I see it, an interpreter is similar to a JIT in that it also translates the bytecode into native code, and the difference is that JIT performs some optimization, like caching.

Is this right? Is there any other major difference?

2
The answer is nonsense, as I stated in a comment a year ago, with three upticks. Self-evident nonsense, too, as there is no apparent distinction between the two definitions given.user207421

2 Answers

2
votes

This statement:

An interpreter generates and executes machine code instructions

Is false.

Simply put, an interpreter is a program that loops over the instructions of a program (be they from a virtual or real instruction set), and executes them one by one. This is done by programming out what each instruction should do and simulating that within the interpreter.

On the most simple level, you could imagine an interpreter looks something like this in general:

for(byte byteCode : program) {
    if(byteCode == ADD_BYTECODE) {
        add();
    }
    // ... others
}

This is not so different a concept from how a CPU executes machine code, but in the case of a CPU, most of the logic is implemented in hardware directly.

I suppose you could say that an interpreter is a program that simulates a CPU in software.


The JIT compiler does the job of translating byte code into machine code and optimizing it along the way too. One of the theoretical advantages of machine code over byte code is for instance that a particular CPU might have specialized instructions available that run faster than the byte code equivalent.

In the case of the JVM this is done when a method is "hot", i.e. when it is ran a lot. JIT compilation takes a long time however (try running a Java program with the -XX:-TieredCompilation -Xcomp flags, which force C2 compilation by default, you'll see the difference in startup time), so it's faster to interpret the byte code first. That also gives the opportunity to collect profiling data, which is data about how the program is running (e.g. how many times an if branch is triggered, or which types are used for dynamic dispatch calls). The profiling data is also used during JIT compilation to do better optimization.

3
votes

I think the above definitions aren't necessarily true.

It isn't "mandatory" or "necessary" that an interpreter translates into machine code.

In essence, an interpreter interprets. It finds a loop, and then "runs" that loop. That is not the same as creating machine code that executes a loop.