0

I have read that some article says

  1. jvm converts byte code to machine code
  2. jvm converts bytecode to native code
  3. jvm converts bytecode to system calls which in turn os communicate with hardware

In the above which one is true? How do translations happen exactly, and what is native code? Is it assembly language code?

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • *intermediate byte code* and just *bytecode* is the same. *machine code* and *native code* is the same. So the first two statements are equivalent (and true). # 3. says something else, the wording may not be the best, but what I think was intended, is true too. – Ole V.V. Jun 30 '19 at 07:52
  • 1
    It's probably a bit more accurate to say that the JVM "**may** translate **some** bytecode to machine (native) code". A JVM is basically a bytecode **interpreter**, but any good JVM also uses JIT ("Just-In-time Translation") to enhance run-time performance of Java apps. – Kevin Anderson Jun 30 '19 at 08:25
  • 2
    The question is too broad as it stands. But some term clarification: machine code = native code. Assembly language is actually a textual representation of machine code (also exists for byte code). System calls are used by programs to access machine resources. They are not part of the "machine language" but are accessible from native languages to access stuff like threads, locks, I/O etc. – RealSkeptic Jun 30 '19 at 08:51
  • #3 only system call will be made for io operations i.e for native methods or for all operations (how jvm interact with os) – Pumpkin bell Jun 30 '19 at 09:54
  • 1
    'Native code' and 'machine code' are the same thing, not two different things. Unclear what you're asking. – user207421 Jun 30 '19 at 10:30
  • My question is jvm won't communicate with Operating system when executing java program? – Pumpkin bell Jun 30 '19 at 11:38
  • Yes, the JVM is communicatint with the operating system while executing a Java program. For example, all input and output goes through the operating system. – Ole V.V. Jun 30 '19 at 13:11

1 Answers1

5

I think the question is poorly structured but there's still a value trying to answer it.

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.

Resources

Juraj Martinka
  • 3,991
  • 2
  • 23
  • 25
  • Hi thanks for the answer, can u give some more clarity in the line "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" - that means **JVM converts bytecode to OS System calls and System calls communicate with hardware to execute machine code?** – Pumpkin bell Jul 08 '19 at 07:21
  • No, JVM doesn't convert bytecode to system calls. System calls are an OS-specific mechanism to carry out only certain operations (e.g. IO, memory allocation, etc.). This isn't really specific to Java/JVM. In bytecode, you just have an invocation of some function which may under the hood be implemented via C standard library (e.g.) on Linux. When the target machine executes the code it will call the standar lib function which executes the system call. See https://cs.stackexchange.com/questions/23463/how-does-an-operating-system-implement-the-c-library for more details. – Juraj Martinka Jul 08 '19 at 15:13