Clarifications on JIT Compiler and Interpreter

I have some doubts about a JIT Compiler and an Interpreter. Starting from their definitions:

(Interpreter) From Wikipedia:

In computer science, an interpreter is a computer program that directly executes, ie performs, instructions written in a programming or scripting language, without previously batch-compiling them into machine language. An interpreter generally uses one of the following strategies for program execution:
1) parse the source code and perform its behavior directly
2) translate source code into some efficient intermediate representation and immediately execute this
3) explicitly execute stored precompiled code[1] made by a compiler which is part of the interpreter system

(JIT COMPILER) From Wikipedia:

In computing, just-in-time compilation (JIT), also known as dynamic translation, is compilation done during execution of a program – at run time – rather than prior to execution.[1] Most often this consists of translation to machine code, which is then executed directly, but can also refer to translation to another format.

and From StackOverFlow:

Just-in-time compilation is the conversion of non-native code, for example bytecode, into native code just before it is executed.

I have 4 questions:
1) It's always said JIT=runtime, why doesn't an Interpreter work at runtime? Doesn't an Interpreter translate and execute each line at runtime, while the program is running?
2) It's always said JIT translates a non-native code to native-code, so what? Doesn't an interpreter convert a code to native code? How can my process execute an instruction if it is not translated to native code? So the interpreter needs to translate the code to native code too.
3) A normal interpreter translates each line when it needs to execute it, while using a JIT compiler each line is translated just before it is executed, so it is aviable in that moment when the line need to be executed. Isn't it?
4) So what are the real differene between an interpreter and a JIT compiler, both executes the program at runtime, both translate from an intermediate language to native code...


An interpreter does not translate source code to native machine code. While your computer is only capable of executing machine code, the machine code that it executes does not necessarily have to be a translation of a higher-level language. Confusing? Let's look at a simple toy example...

Consider the programming language PrintForPony that has two functions, print and sleep . The print function takes a string of characters as its only argument and prints it to stdout, while sleep takes a positive integer as its only argument and puts the current thread to sleep for that amount of time. A pseudo-BNF for PFP:

program        ::= statement_list
statement_list ::= statement | statement NEWLINE statement_list
statement      ::= print STRING | sleep POSITIVE_INTEGER

Here's a super simple Java-implementation of an intepreter for PFP. The program takes a source file as its only argument and interprets it:

import java.io.BufferedReader;
import java.io.FileReader;

public class PFPInterpreter {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(args[0]));
        String line = null;
        while ((line = br.readLine()) != null) {
            if (line.startsWith("print ")) {
                System.out.println(line.substring("print ".length()));
            } else if (line.startsWith("sleep ")) {
                Thread.sleep(Long.parseLong(line.substring("sleep ".length())));
            } else {
                throw new IllegalArgumentException("Unknown function: " + line);
            }
        }
    }
}

A sample source file:

print Hello, World!
sleep 1000
print Goodbye, World!

And sample output:

$ java PFPInterpreter test.pfp 
Hello, World!
Goodbye, World!

At no point in time is PFP translated into native machine code. The native machine code that is executed is the JVM, which has nothing to do with this toy language. We could also write a compiler for PFP that would translate the code into an executable file (I'm not going to, because this answer is already getting too long), but the point of the matter is that an interpreter does not compile to native machine code - it reads an input file and does something based on the contents.

To answer the questions:

1) An interpreter is the runtime that runs your code for you. I'm not sure exactly where you've read that interpreters don't work at runtime, but I'm also not sure what it's supposed to mean.

2) As demonstrated above, no, an interpreter does not translate to native machine code. A JIT-compiler does. Your processor only executes native machine code, but that native machine code could be a program that reads an arbitrary file and does something based on the contents. In that sense, an interpreter is really just a typical program that accepts input in the form of text files.

3) JIT-compilation is pretty complicated, and I am not an expert at all. However, with Java's HotSpot, for instance, code blocks must be executed a certain amount of times (1,500 for client, 15,000 for server, IIRC) before the JIT-compiler is invoked on them. This is likely because the actual compilation is not free, and it's very likely that the compiled native machine code is cached for later executions (which would explain the requirement of many executions). This makes JIT-compilation is an investment (in time and space) that may not be faster (perhaps even slower) on the first execution, but subsequent executions will be faster because compilation is no longer necessary, and the native machine code is more efficient.

4) See above.

I hope that helps!


1) It's always said JIT=runtime, why doesn't an Interpreter work at runtime? Doesn't an Interpreter translate and execute each line at runtime, while the program is running?

You are correct; interpretation necessarily occurs at run time.

2) It's always said JIT translates a non-native code to native-code, so what? Doesn't an interpreter convert a code to native code? How can my process execute an instruction if it is not translated to native code? So the interpreter needs to translate the code to native code too.

It's true that all execution is ultimately native code. The interpreter is filled with functions that implement the effects of non-native interpreted instructions. Those functions are in native code.

3) A normal interpreter translates each line when it needs to execute it, while using a JIT compiler each line is translated just before it is executed, so it is aviable in that moment when the line need to be executed. Isn't it?

4) So what are the real differene between an interpreter and a JIT compiler, both executes the program at runtime, both translate from an intermediate language to native code...

The difference is that JIT can be applied to sections of code larger than just a single statement or instruction—JIT may be used to compile whole functions, classes, or even the entire program.

The advantage of JIT compilation is that, in exchange for the one-time cost of compiling a portion of the interpreted code into native code, you are saving the execution overhead of interpretation as well as exploiting optimizations that can't be performed when you only have a single-instruction-at-a-time view of the non-native code as an interpreter does.

This is why it makes sense to JIT compile portions of code that are executed repeatedly. The cost of compilation is incurred only once, while the benefits are reaped for each use of the code.


Here I will directly answers to last question.

Sometimes the Java Virtual Machine is called the Java interpreter; however, given the various ways in which bytecodes can be executed, this term can be misleading. While "Java interpreter" is a reasonable name for a Java Virtual Machine that interprets bytecodes, virtual machines also use other techniques (such as just-in-time compiling) to execute bytecodes. Therefore, although all Java interpreters are Java Virtual Machines, not all Java Virtual Machines are Java interpreters.

JIT refers to execution engine in few of JVM implementations, one that is faster but requires more memory,is a just-in-time compiler. In this scheme, the bytecodes of a method are compiled to native machine code the first time the method is invoked. The native machine code for the method is then cached, so it can be re-used the next time that same method is invoked.

链接地址: http://www.djcxy.com/p/52562.html

上一篇: 在使用Python解释器时,编译器是否可以使用?

下一篇: 关于JIT编译器和解释器的说明