0

When will JVM convert bytecode to machine code? 1. Only once per class during class loading? 2. While creating each object of a class, example Student object from Student class? 3. Or during each method call?

How will this be in sync with the method stack during the method calls.

  • Re. the first question: I think it depends on the command line options and the JVM. I'm pretty sure that historically the `-server` switch on the command line cause all byte codes to be compiled before any execution. However I believe nowadays that all 64 bit JVMs precompile byte codes, whether they're running as a server or not. – markspace Oct 24 '18 at 03:35
  • This page may be relevant, although some of the info appears to be quite old. https://stackoverflow.com/questions/198577/real-differences-between-java-server-and-java-client – markspace Oct 24 '18 at 03:39
  • 1
    On this page it says that 64 bit JVMs imply the `-server` option: https://docs.oracle.com/javase/10/tools/java.htm – markspace Oct 24 '18 at 03:43
  • @markspace correct, there never was a “client” 64 bit JVM (in case of HotSpot). But the differentiation between client and server JVMs has been superseded by “tiered compilation” anyway. Simply said, the JVM still starts in interpreted mode, but will quickly compile frequently used methods with the tier1 compiler (equivalent to client), but spent more time on profiling and optimization the hottest spots using the tier2 compiler (equivalent to server). – Holger Oct 24 '18 at 14:18

2 Answers2

1
  1. Only once per class during class loading?
  2. While creating each object of a class?
  3. During each method call?

None of the above!

When the class is first loaded, the JVM will interpret the bytecodes when a method is called to gather some statistics. After a bit, the JVM will pick methods that have been called a few times and compile those methods to native code.

But that's not the end. In some circumstances, the JIT compiler may actually recompile / reoptimize a method that it has already compiled. This can happen if (for example) another class is loaded (lazily or dynamically) that invalidates the basis for a previous optimization.


How will this be in sync with the method stack during the method calls.

Deep implementation details. (But I think that the stack layout is the same for a method when interpreting bytecodes and and running compiled native code.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • My understanding is that the layout of objects and the stack are unchanged by JIT compilation, however, it could be in future. – Peter Lawrey Oct 24 '18 at 11:35
  • 1
    Yes ... and if (hypothetically) a future JIT compiler is able to change stackframe layouts, it will also need to deal with the problem of compiling a method that is currently being executed ... on some thread. – Stephen C Oct 24 '18 at 12:31
  • Actually, the stack layout can differ significantly. The first thing to notice, is that compiled code needs much less stack space. Which is easy to explain, considering method inlining, elimination of unused and redundant variables, and using CPU registers. But why should it be “in sync” at all? The only thing, which matters, is the ability to pass arguments and return values between caller and callee when invoking a compiled method from interpreted code and vice versa. And, the JVM records the origin of the code to be able to reconstruct the stack trace, at least at certain *safe points*. – Holger Oct 24 '18 at 13:58
  • @Holger - So what happens if a method is compiled while a call to it is in progress? (I assume that can happen ...) How is the compiled method able to cope with local variables created in the interpreted version of the method; e.g. when you return into the method from a call to something else? – Stephen C Oct 24 '18 at 14:40
  • The normal mode is to compile for the next method entry and leave the current execution unaffected. If it is a long running method, the JVM may decide to use “On Stack Replacement” (OSR). The requirement to receive control from the interpreted execution must be known before compiling, as it will change the resulting code and may reduce the effectiveness of the optimizations. There will be a general distinction between the code registered in a vtable, to be entered on the next invocation, and the code compiled for OSR. The latter may be dropped, once all actual executions have been completed. – Holger Oct 24 '18 at 14:45
1

"When it feels like it". I don't mean to be frivolous, but there's no general answer.

A JVM can either interpret bytecode, or compile it to the native machine code. Machine code runs faster, but it costs time and space to compile it. There's therefore a tradeoff to be made, and there are no requirements to handle the tradeoff one way or another. Indeed, it can vary from one JVM to another, or one version to another.

The subject is called "Just In Time" compilation (JIT) and there will be different implementations. Consult your JVM documentation.

My guess is that a likely mechanism is to notice that the same method has been executed "some number of times" and would therefore benefit from being compiled to machine code. i.e, your #3 answer is probably closest.

dave
  • 103
  • 2