JIT编译代码驻留在哪里?

时间:2015-01-24 13:40:03

标签: java jvm jit

所以我有这个用Java编写的方法:

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

并假设我的应用程序多次调用它..

在Java虚拟机上运行此方法的已编译代码时,JVM将首先解释该方法。然后经过一段时间后,如果我理解正确,它将决定将其编译为机器语言。

此时,

是否会被内存中的机器代码覆盖?如果被覆盖,那么尺寸差异的问题将如何解决?如果它被写入内存中的其他位置,那么加载到内存中的字节码是否会被释放?而且,如果字节码和jit编译的代码都在内存中,当应用程序再次遇到此方法时,JVM如何决定执行jit编译的代码而不是字节代码?

3 个答案:

答案 0 :(得分:13)

HotSpot JVM在Metaspace(或早期版本的PermGen)中具有Method结构。 它包含永远不会覆盖的方法字节码和a pointer to compiled code,在编译方法之前最初为NULL。

方法可能有多个入口点:

  • _i2i_entry - 指向字节码解释器的指针。
  • _code->entry_point() - JIT编译代码的入口点。编译后的方法驻留在CodeCache - VM动态生成代码的本机内存的特殊区域。
  • i2cc2i适配器从解释器调用已编译的代码,反之亦然。这些适配器是必需的,因为解释的方法和编译的方法具有不同的调用约定(如何传递参数的方式,如何构造帧等)。

在某些极少数情况下,编译后的方法可能会有不常见的陷阱,这些陷阱可以回溯到解释器。此外,Java方法可以多次动态重新编译,因此JVM不能丢弃原始字节码。无论如何都没有意义释放它,因为字节码通常比编译的代码小得多。

答案 1 :(得分:5)

不,它没有被覆盖,因为这两个表示在同一个地方通常没有实际的好处。 JVM字节码只是一段数据。 JIT发出的代码是本机CPU指令流(在某些体系结构中,要求将其明确标记为可执行文件)。

通常,当执行需要新函数时,JIT编译器读取该函数的字节码,在其他地方分配内存,将等效的本机代码写入该内存,然后返回一个函数指针指向新生成的条目本地代码。

答案 2 :(得分:2)

据我所知,The Java® Virtual Machine Specification并未指明任何内容 我可以找到对JIT的唯一引用是Chapter 3

  

[...]此类转换器的一个示例是即时(JIT)代码生成器,它仅在加载Java虚拟机代码后生成特定于平台的指令。本章不涉及与代码生成相关的问题,只涉及与使用Java编程语言编写的源代码编译为Java虚拟机指令相关的问题。

所以根据我的理解,这可以通过不同的实现以不同的方式完成。

然而,对我而言,包含java字节码的内存似乎不太可能被本机CPU指令覆盖,因为CPU指令在技术上是可执行的,字节码只是数据,因为它必须被解释。但这不可能是非常奇怪的。