Where is the compiled JIT code located?

So, I have this method written in Java:

public void myMethod(int y){ int x = 5 + y; doSomething(x); } 

And suppose my application calls this many times.

When you run the compiled code for this method on the Java virtual machine, the JVM first interprets this method. Then after a while he decides to compile it into machine language, if I understand correctly.

In this moment

Will it be overwritten by machine code in memory? If it is overwritten, how will the difference in size problem be solved? If it is written to another location in memory, will the bytecode be freed, loaded into memory, or not? And also, if both the bytes and jit compiled code are in memory when the application calls this method again, how does the JVM decide to execute the compiled jit code instead of the byte code?

+7
java jvm jit
source share
3 answers

HotSpot JVM has a Method structure in Metaspace (or PermGen in earlier versions). It contains a bytecode method that is never overwritten, and a pointer to the compiled code , initially NULL, until the method is compiled.

A method can have several entry points:

  • _i2i_entry - pointer to the bytecode interpreter.
  • _code->entry_point() is the entry point to the JIT-compiled code. Compiled methods reside in CodeCache , a special area of โ€‹โ€‹internal memory for dynamically generated VM code.
  • i2c and c2i to invoke compiled code from the interpreter and vice versa. These adapters are necessary because the interpreted methods and compiled methods have different calling conventions (the method of passing arguments, how frames are created, etc.).

A compiled method may have unusual traps that return to the interpreter in some rare cases. In addition, the Java method can be dynamically recompiled several times, so the JVM cannot throw away the source bytecode. In any case, it makes no sense to free it, because the bytecode is usually much smaller than the compiled code.

+12
source share

No, this is not overwritten, because there is usually no practical advantage in two views located in the same place. The JVM bytecode is just a piece of data. JIT-emitted code is a stream of built-in CPU instructions (some architectures require this to be explicitly marked as executable).

Usually, when a new function is required to execute, the JIT compiler reads the bytecode of this function, allocates memory elsewhere, writes the equivalent native code to this memory, and then returns the function pointer to write the newly created native code.

+5
source share

As far as I know, the Javaยฎ Virtual Machine Specification does not specify any of them.
The only JIT link I can find is in Chapter 3 :

[...] One example of such a translator is the Just-in-Time Code Generator (JIT), which generates instructions on the platform only after loading Java Virtual Machine code. This chapter does not address code generation issues, only those related to compiling source code written in the Java programming language, Java Virtual Machine instructions.

Therefore, as I understand it, this can be done in different ways using different implementations.

However, it seems unlikely to me that the memory containing the java bytecode is overwritten with the instructions of the main processor, because the CPU instructions are technically executable, and the bytecode is just data, as it needs to be interpreted. That would be impossible, but very strange.

+2
source share

All Articles