我没有使用过生产质量的虚拟机,但这是我的 5 美分。
.text
Unix 可执行文件中的部分属于存储可执行代码的文件;在运行时,这个文件部分被映射到系统链接器在程序初始化期间分配的内存区域,仅此而已(在 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]
这里rw-p
意味着[heap]
不能执行任何数据(尽管,例如,没有 PAE 的 32 位 x86 CPU 不是这种情况,它们没有硬件能力来阻止将某些内存数据作为代码运行),但可以读取/书面。
因此,VM 需要具有代码执行权限的专用内存区域。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
然后本地代码的执行是组装 JIT 编译的本地代码的问题,或者与位置无关(如编译共享对象代码,使用gcc
option -fPIC
)或使用mmap()
.