How does Java code translate to machine code?

I can see your confusion and the problem is that the real mechanics of Java Interpreter are actually quite different from what you may imagine when you just read a high-level description of an interpreter.

To start with, Java (or another JVM-based language) source code is compiled into bytecode via javac. This produces a relatively simple .class file format which may contain ~200 bytecodes - this isn't a format that is directly executable by any real computer; rather it's a format designed to be executed by a "virtual machine", that is the JVM.

Therefore, to be able to execute compiled java programs on real machines we need to "convert" them into an executable representation, that is machine code (the same thing as native code).

By default, the JVM acts as an interpreter: that means the .class files are read and executed one bytecode (opcode) at a time. The role of the interpreter is to read the opcode and execute a corresponding action - this is where it gets more complicated...

Normally, you'd expect that the interpreter would have a big switch statement covering all possible opcodes and executing appropriate actions based on the bytecode it encounters like:

switch (opcode) {
  case iconst_1: handleIConst1();

This code would be part of the interpreter (that is the JVM itself) and would be compiled to the machine code ahead of time - you get this when you install an OS-specific version of JVM/JDK.

However, the JVM interpreter is a special type called Template Interpreter. It doesn't contain a hardcoded logic but actually maintains a table of mappings between opcodes and machine code. This table is populated when the JVM is starting (you can see it via -XX:+PrintInterpreter -> requires the hsdis library). Later on, when JVM starts interpreting bytecodes the interpreter will check in the table whether it has a corresponding entry to the code cache where the machine code resides. If so, then it executes the machine code directly; otherwise it can fallback to resolving the bytecode dynamically.

So we have the interpreter which executes bytecodes one-by-one. Moreover, there's also JIT which is used if some method is "hot enough" (called thousands of times). The JIT will kick in and takes place of the interpreter - it will compile the whole method into native code which is then executed on the target machine.

Finally, the issue of system calls is unrelated to this matter. System calls have to be used by any program that wants to access hardware or other sensitive resources. They are not part of your program, rather they are provided by the OS.

Java is a platform-independent programming language. It means that we can run Java on the platforms that have a Java interpreter. It is the reason that makes the Java platform-independent. The Java interpreter converts the Java bytecode (.class file) into the code understand by the operating system.

In this section, we will understand what is an interpreter in Java, the features of the interpreter, and how does the Java interpreter work. We will also see how it is different from a compiler.

What is an interpreter in Java?

Java interpreter is a computer program (system software) that implements the JVM. It is responsible for reading and executing the program. It is designed in such a way that it can read the source program and translate the source code instruction by instruction. It converts the high-level program into assembly language (machine language).

How does the Java interpreter work?

To convert the byte code into machine code, we deploy the .class file on the Java Virtual Machine (JVM). The JVM converts that code into machine code using the Java interpreter. The JVM uses the interpreter at runtime, after that it execute the code on the host machine.

How does Java code translate to machine code?

As the Java compiler compiles the source code into the Java bytecode. In the same way, the Java interpreter converts or translates the bytecode into the machine-understandable format i.e. machine code, after that the machine code interacts with the operating system.

If the JVM is installed on any system it means that the platform is JVM enabled. The platform performs all the tasks of the Java run-time system. It loads the Java class file and interprets the compiled byte-code.

The browsers, like Google Chrome, Netscape, etc. are the popular example that contains the Java interpreter. It means these are Java-enabled browsers. It is used to run the Applet in the browser. The interpreter also serves as a specialized compiler in an implementation that supports dynamic or just-in-time (JIT) compilation which turns the Java bytecode into native machine instructions.

Let's see how an interpreter loads a Java program.

First, we specify the class by using the java command followed by the class name and options available for the interpreter, and command-line arguments if required. We use the following command to load the class:

In the above command, the class name should be a fully qualified name (the name of the class that includes the package name, if any). Remember that, we do not write the .class extension at the end of the class name. For example:

In the first command, Product is the class name. In the second command, com.javatpint.product is the name of the package in which the Mobile class is stored.

Once the class is loaded, Java follows a convention and searches for the class that contains the main() method. When the JVM founds the main() method, the interpreter starts the application by invoking the main() method. After executing the main() method, additional threads, and references other classes.

Features of Interpreter

It converts the source code into machine language, line by line at run time, without changing the sequence.

  • An interpreter does not generate an intermediate machine code
  • Each error of every line is displayed one by one
  • When compared to a compiler, the program execution speed is slower
  • Less amount of time is spent on analyzing and processing the program

Difference Between Interpreter and Compiler

In the following table, we have summarized the key differences between an interpreter and a compiler.

How is a Java program typically translated?

The Java compiler translates Java programs into a language called Java bytecode. Although bytecode is similar to machine language, it is not the machine language of any actual computer. A Java interpreter is used to run the compiled Java bytecode program.

Does Java compile to machine code?

Java is a compiled programming language, but rather than compile straight to executable machine code, it compiles to an intermediate binary form called JVM byte code. The byte code is then compiled and/or interpreted to run the program.

How are language translated into machine code?

Compilers are used to translate a program written in a high-level language into machine code (object code). Once compiled (all in one go), the translated program file can then be directly used by the computer and is independently executable.

How does JVM convert bytecode to machine code?

The java compiler converts high-level java code into bytecode (which is also a type of machine code). In Java, the Just In Time Code generator converts the bytecode into the native machine code which are at the same programming levels. Hence, Java is both compiled as well as interpreted language.