拆解Java JIT编译的本地字节码

29

有没有办法对Java即时编译器生成的本地代码进行汇编转储?

另一个相关问题:有没有办法在不运行JVM的情况下使用JIT编译器将我的代码编译成本机机器代码?


1
异端邪说!不过开个玩笑。有趣的问题!+1 - Prof. Falken
您如何访问这个“即时编译”的代码?因为它是在运行时动态生成的,所以我想知道如何访问它并进行汇编转储... - Manuel Selva
4
你的第一个问题很奇怪,但第二个问题建议你应该阅读一些相关的资料。按照 JIT 编译的定义,它依赖于只有在运行时才能获得的信息,就像你正在问是否有任何方法可以在没有先录制歌曲的情况下使用 MP3 编码器对歌曲进行编码一样。 - entonio
3
gdb适用于调试HotSpot。您可能希望生成OpenJDK的Debug版本,这比较容易。至于您的第二个问题 - 有几个Java AOT编译器可用。例如,gcj可以将字节码编译成本机代码。 - SK-logic
5个回答

17

是的,有一种方法可以打印生成的本地代码(需要 OpenJDK 7)。

不,没有一种方法使用 JDK 的 JIT 将您的 Java 字节码编译为本地代码并将其保存为本机可执行文件。

即使这是可能的,它可能并不像您想象的那样有用。JVM 进行了一些非常复杂的优化,并且如果需要,它甚至可以在运行时动态取消优化。换句话说, JIT 编译您的代码到本机机器语言并不像您想象的那样简单,而且当程序正在运行时,本机机器语言也不会保持不变。此外,这也不能让您创建独立于 JVM 和运行时库的本机可执行文件。


4
如果Amigable Clark Kant认为你的问题是异端邪说,那么他看到这个答案肯定会更加愤怒。将其归类为“可能性”,而不是“Justin推荐”。 :-)
一种选择是使用IKVM.NET来使用Mono处理您的Java代码。 IKVM.NET允许您在.NET或Mono CLR之上运行Java代码。有些人可能会说,这样可以跳过JVM,尽管更准确地说,IKVM.NET实际上是在CLR上运行的JVM实现。
无论如何,如果您这样做,现在就可以使用Mono进行Ahead-of-time (AOT)编译您的代码。也就是说,您可以将代码编译成机器本地代码,这意味着您在运行时不需要CLR或JVM。
与 Jesper 在上面说的不同,使用 AOT 编译实际上可以带来更好的性能。虽然在运行时 JVM(和 CLR)执行了一些无法在编译时进行的优化,但反之亦然。此外,其中一个选项是使用 LLVM 进行代码生成,这通常会导致更好的性能。
以下是简要概述的流程:
您的代码 -> IKVM.NET -> Mono -> LLVM -> 本机可执行文件
或者,只需使用专门设计用于从头开始 AOT 生成本机可执行文件的 Java 编译器(例如 GCJExcelsior Jet)。
Mono/IKVM.NET 选项可能有用的一个地方是,如果您想在 iPhone 应用程序中使用 Java 库(使用 MonoTouch),则 App Store 只允许本机二进制文件。 编辑:你也可以使用LLVM VMKit将Java代码AOT编译成机器代码。这在概念上与我描述的Mono过程相同,但避免了那些令人讨厌的CIL内容。

3

你不能使用JIT生成独立的可执行文件,你需要像GCJ这样的其他系统。至于查看JIT生成的代码,请查看OpenJDK源代码以寻找调试选项。你可以构建启用了这些选项的自己的副本,并查看JIT正在做什么,或添加自己的增强功能以输出任何你想要的内容。


1

我也认为获取JIT本地输出很难,但是这篇文章展示了本地代码,但没有说明如何获得输出。我可以理解如果JIT编译器的输出会不一致,因为它会随着时间的推移而改变或从代码缓存中清除,只能在以后重新生成,但是如何快速获取某些代码块的汇编快照呢。

http://www.google.com/url?sa=t&rct=j&q=Java+annotation+for+optimization&source=web&cd=15&ved=0CKEBEBYwDg&url=http%3A%2F%2Floome.cs.uiuc.edu%2Fpubs%2Fjones-kamin.pdf&ei=8vj-UN63C-bQ2QX-9IDoDQ&usg=AFQjCNEegMNXLwKyUTTJ5ljgnP7X9rPXHg&bvm=bv.41248874,d.b2I


1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接