为什么 JVM 不缓存 JIT 编译的代码?
Sun 的规范 JVM 实现对字节码应用了一些相当复杂的优化,以便在代码运行几次后获得接近本机的执行速度。
问题是,为什么不将此编译后的代码缓存到磁盘以供后续使用同一函数/类时使用?
按照目前的情况,每次执行程序时,JIT 编译器都会重新启动,而不是使用代码的预编译版本。当字节码本质上被解释时,添加此功能不会显着增加程序的初始运行时间吗?
The canonical JVM implementation from Sun applies some pretty sophisticated optimization to bytecode to obtain near-native execution speeds after the code has been run a few times.
The question is, why isn't this compiled code cached to disk for use during subsequent uses of the same function/class?
As it stands, every time a program is executed, the JIT compiler kicks in afresh, rather than using a pre-compiled version of the code. Wouldn't adding this feature add a significant boost to the initial run time of the program, when the bytecode is essentially being interpreted?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果没有对 @MYYN 发布的链接进行剪切和粘贴,我怀疑这是因为 JVM 执行的优化不是静态的,而是基于数据模式和代码模式的动态优化。这些数据模式很可能会在应用程序的生命周期内发生变化,从而导致缓存的优化效果不佳。
因此,您需要一种机制来确定保存的优化是否仍然是最佳的,此时您不妨即时重新优化。
Without resorting to cut'n'paste of the link that @MYYN posted, I suspect this is because the optimisations that the JVM performs are not static, but rather dynamic, based on the data patterns as well as code patterns. It's likely that these data patterns will change during the application's lifetime, rendering the cached optimisations less than optimal.
So you'd need a mechanism to establish whether than saved optimisations were still optimal, at which point you might as well just re-optimise on the fly.
Oracle 的 JVM 确实有记录这样做 - - 引用甲骨文,
我不知道为什么所有复杂的虚拟机实现都不提供类似的选项。
Oracle's JVM is indeed documented to do so -- quoting Oracle,
I don't know why all sophisticated VM implementations don't offer similar options.
对现有答案的更新 - Java 8 有一个 JEP 致力于解决这个问题:
=>
JEP 145:缓存编译代码。 新链接。在非常高的层面上,其既定的目标是:
希望这有帮助。
An updated to the existing answers - Java 8 has a JEP dedicated to solving this:
=>
JEP 145: Cache Compiled Code. New link.At a very high level, its stated goal is:
Hope this helps.
Excelsior JET 从 2.0 版开始就有一个缓存 JIT 编译器,早在2001。此外,它的 AOT 编译器可能会使用所有优化将缓存重新编译为单个 DLL/共享对象。
Excelsior JET has a caching JIT compiler since version 2.0, released back in 2001. Moreover, its AOT compiler may recompile the cache into a single DLL/shared object using all optimizations.
我不知道真正的原因,没有以任何方式参与 JVM 实现,但我可以想到一些看似合理的原因:
但我确实在猜测,正如您所看到的,我真的不认为有任何优化我的原因之一是真正的阻碍。我认为 Sun 并没有将这种支持视为优先事项,也许我的第一个原因接近事实,因为习惯性地这样做可能还会导致人们认为 Java 类文件确实需要为每个 VM 提供单独的版本,而不是单独的版本。跨平台。
我更喜欢的方法实际上是拥有一个单独的字节码到本机翻译器,您可以使用它预先明确地执行类似的操作,创建为特定虚拟机显式构建的类文件,其中可能包含原始字节码,以便您也可以与不同的虚拟机一起运行。但这可能来自我的经验:我主要从事 Java ME,Java 编译器在编译方面并不更智能,这确实很糟糕。
I do not know the actual reasons, not being in any way involved in the JVM implementation, but I can think of some plausible ones:
But I really am guessing, and as you can see, I don't really think any of my reasons are actual show-stoppers. I figure Sun just don't consider this support as a priority, and maybe my first reason is close to the truth, as doing this habitually might also lead people into thinking that Java class files really need a separate version for each VM instead of being cross-platform.
My preferred way would actually be to have a separate bytecode-to-native translator that you could use to do something like this explicitly beforehand, creating class files that are explicitly built for a specific VM, with possibly the original bytecode in them so that you can run with different VMs too. But that probably comes from my experience: I've been mostly doing Java ME, where it really hurts that the Java compiler isn't smarter about compilation.