JVM/CLR如何执行JIT编译的本地代码?是通过代码注入还是通过将代码复制到可执行内存?哪些系统调用允许动态代码执行?
aurhwmvo1#
我可以在CACAO VM中解释我们是如何做到的首先,方法的机器码被生成到一些堆分配的内存块中。编译之后,最终的代码长度是已知的,并且使用mmap和PROT_EXEC标志分配可执行内存块。(此处为相关的CACAO代码)。然后,机器代码被复制到mmapped区域。之后,许多架构需要一些机器特定的缓存刷新机制。作为示例,请查看PowerPC 64的缓存刷新功能。值得注意的是,在i386和x86_64上,不需要执行任何操作。完成此步骤后,处理器就可以执行新生成的代码了。或者,可以使用mprotect将已分配的内存页标记为可执行。请注意,mmap/mprotect是Unix工具。
mmap
PROT_EXEC
mprotect
bfnvny8b2#
我不知道Java具体是怎么做到的,但一般来说,你会在解释器的指令流中插入“trap”操作码。如果你想知道确切的答案,没有比来源更好的答案了:http://download.java.net/jdk6/source/
hc2pp10m3#
公共语言运行库为每种类型都提供了一个方法表,其中的项指向本机代码或指向JIT托管代码的本机存根,然后使用指向刚创建的本机代码的指针修复方法表。MSDN在MethodDesc部分有更深入的explanationThis blog entry by Dave Notario说明CLR JIT编译器的运作方式。
3条答案
按热度按时间aurhwmvo1#
我可以在CACAO VM中解释我们是如何做到的首先,方法的机器码被生成到一些堆分配的内存块中。编译之后,最终的代码长度是已知的,并且使用
mmap
和PROT_EXEC
标志分配可执行内存块。(此处为相关的CACAO代码)。然后,机器代码被复制到mmapped区域。之后,许多架构需要一些机器特定的缓存刷新机制。作为示例,请查看PowerPC 64的缓存刷新功能。值得注意的是,在i386和x86_64上,不需要执行任何操作。完成此步骤后,处理器就可以执行新生成的代码了。或者,可以使用mprotect
将已分配的内存页标记为可执行。请注意,mmap
/mprotect
是Unix工具。bfnvny8b2#
我不知道Java具体是怎么做到的,但一般来说,你会在解释器的指令流中插入“trap”操作码。
如果你想知道确切的答案,没有比来源更好的答案了:http://download.java.net/jdk6/source/
hc2pp10m3#
公共语言运行库为每种类型都提供了一个方法表,其中的项指向本机代码或指向JIT托管代码的本机存根,然后使用指向刚创建的本机代码的指针修复方法表。
MSDN在MethodDesc部分有更深入的explanation
This blog entry by Dave Notario说明CLR JIT编译器的运作方式。