为什么JVM没有缓存JIT编译代码?

时间:2010-01-02 19:06:11

标签: java caching jvm compilation jit

Sun的规范JVM实现将一些非常复杂的优化应用于字节码,以便在代码运行几次后获得接近本机的执行速度。

问题是,为什么这个编译的代码不能缓存到磁盘上以便在后续使用同一个函数/类时使用?

就目前而言,每次执行程序时,JIT编译器都会重新启动,而不是使用预编译版本的代码。当字节码基本上被解释时,不会添加此功能会大大增加程序的初始运行时间吗?

5 个答案:

答案 0 :(得分:25)

确实记录了

Oracle's JVM - 引用Oracle,

  

编译器可以利用   Oracle JVM的类解析模型   可选地持久编译Java   跨数据库调用的方法,   会话或实例。这样   持久性避免了开销   不必要的重新编译   会话或实例,如果是   已知在语义上是Java代码   没有改变。

我不知道为什么所有复杂的VM实现都不提供类似的选项。

答案 1 :(得分:25)

不依赖于@MYYN发布的链接的'cut'n',我怀疑这是因为JVM执行的优化不是静态的,而是动态的,基于数据模式和代码模式。这些数据模式可能会在应用程序的生命周期内发生变化,从而使缓存的优化不是最佳的。

所以你需要一种机制来确定保存的优化是否仍然是最优的,此时你也可以在运行中重新进行优化。

答案 2 :(得分:14)

更新到现有答案 - Java 8有一个致力于解决此问题的JEP:

=> JEP 145: Cache Compiled Code New link

在非常高的水平上,其声明的目标是

  

保存并重用以前运行的已编译本机代码   改善大型Java应用程序的启动时间。

希望这会有所帮助。

答案 3 :(得分:5)

Excelsior JET 自2001年发布以来版本2.0的缓存JIT编译器。此外,它的AOT编译器可以使用所有优化将缓存重新编译为单个DLL /共享对象。 / p>

答案 4 :(得分:0)

我不知道实际的原因,不是以任何方式参与JVM实现,但我可以想到一些看似合理的原因:

  • Java的想法是一种一次写入运行的语言,将预编译的东西放入类文件中就是违反了这一点(只有“种类”,因为实际的字节代码当然仍然存在)
  • 它会增加类文件的大小,因为你会多次使用相同的代码,特别是如果你碰巧在多个不同的JVM下运行相同的程序(当你认为不同的版本是不同的JVM时,这并不是很常见) ,你真的要做)
  • 类文件本身可能不可写(虽然检查它很容易)
  • JVM优化部分基于运行时信息,而在其他运行中,它们可能不适用(尽管它们仍应提供一些好处)

但我真的在猜测,正如你所看到的,我并不认为我的任何理由都是真正的表现。我认为Sun并不认为这种支持是优先考虑的事情,也许我的第一个理由是接近事实,因为习惯性地这样做也可能导致人们认为Java类文件确实需要为每个VM提供单独的版本而不是跨平台。

我首选的方法实际上是拥有一个单独的字节码到本机转换器,您可以使用它来事先明确地执行此类操作,创建为特定VM显式构建的类文件,其中可能包含原始字节码这样你就可以运行不同的虚拟机了。但这可能来自我的经验:我一直在做Java ME,它真的很痛苦,Java编译器对编译并不聪明。