当java jvm编译字节码时,该代码在进程空间中的哪个位置?

Ale*_*ird 8 java memory jvm process jvm-hotspot

当jvm(在我的情况下是热点)永久地将某些代码路径编译成机器代码时,存储的机器代码在哪里?在进程内存的.text段?在进程的堆?

我不是在谈论JITing.根据我的理解,JIT将编译并运行字节码,而无需将编译代码保存在任何地方.可是你知道当JVM 节省代码-凡在进程空间中它保存呢? ......正如评论和答案所指出的那样,我要求的一切事实上都是JIT的一部分.

编辑:

根据我在下面的评论,我特别提到的情况在这里记录为"自适应优化":http://www.oracle.com/technetwork/java/whitepaper-135217.html#hotspot

Dmy*_*nko 5

我没有使用过生产质量的虚拟机,但这是我的五美分。

.textUnix 可执行文件中的节属于存储可执行代码的文件;在运行时,该文件节被映射到程序初始化期间由系统链接器分配的内存区域,仅此而已(在 Linux 上,您可以在 中看到内存中的节布局/proc/$PID/maps)。

至于类 Unix 系统上的 JIT 编译,我只能想到由启用标志的系统调用分配的内存mmap区域PROT_EXEC。此调用由 POSIX 标准指定,并由 Linux 的系统链接器使用,ld.so将任何本机可执行文件加载到内存中。该调用同样可以用于在运行时分配新的可执行内存区域。

通常的堆通常受到 OS/ MMU的保护,以免被执行,正如任何/proc/$PID/maps文件所暗示的那样:

00dd4000-01292000 rw-p 00000000 00:00 0                  [heap]
Run Code Online (Sandbox Code Playgroud)

这里rw-p意味着没有数据[heap]可以被执行(尽管,例如,没有 PAE 的 32 位 x86 CPU 就不是这种情况,它们没有硬件能力来阻止将某些内存数据作为代码运行),但可以读取/书面。

因此,虚拟机需要一块具有代码执行权限的专用内存区域。rwx事实上,让我们在一些 java 进程内存布局中寻找内存区域:

# cat /proc/12929/maps | grep rwx        # I run a Java VM with PID 12929
f3700000-f3940000 rwxp 00000000 00:00 0  # - an unnamed executable & writable region
Run Code Online (Sandbox Code Playgroud)

gcc然后,本机代码的执行就是位置无关地组装 JIT 编译的本机代码(就像使用选项编译共享对象代码-fPIC)或使用 所返回的地址mmap()


sel*_*lig 3

首先,您所描述的是 JIT - 特别是它在 Hotspot 中的工作原理

要回答有关代码在运行时保存在何处的问题- 它位于进程堆中,并且对象的 Klass 文件中指向方法代码的指针已更新以指向它。还有一种称为 OSR(堆栈替换)的工具,用于直接在堆栈上编译长时间运行的循环。