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


107

Sun的规范JVM实现对字节码进行了一些相当复杂的优化,以在代码运行几次后获得接近本机的执行速度。

问题是,为什么不将编译后的代码缓存到磁盘上以供以后使用同一功能/类时使用?

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



2
但是,一个不太可能引起肯定性回答的问题。
bmargulies 2010年

1
我不确定“显着”的提升,因为那样的话,您将不得不从磁盘加载JITted的内容,而不是在内存中进行JIT。它可以加快速度,但要视具体情况而定。
R. Martinho Fernandes

1
感谢大家的好评!所有答案都同样有效,因此我与社区一起参加了这一活动……
Chinmay Kanchi 2010年

如果您问我,这是一个很好的问题:)
Alfred

Answers:


25

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

因此,您需要一种机制来确定所保存的优化是否仍然是最佳的,这时您可能还需要即时进行优化。


6
...或者您可以像Oracle的JVM一样,提供持久性作为选项,从而使高级程序员可以在他们只知道模式没有改变的情况下,在他们的责任下,优化应用程序的性能。为什么不?!
亚历克斯·马丁里

2
因为这可能不值得。如果SUN,IBM和BEA都不认为它们对于性能JVM值得,那么将有充分的理由。也许他们的RT优化比Oracle更快,这就是Oracle对其进行缓存的原因。
skaffman 2010年

9
为什么不使用存储的优化作为起点,以使用先前运行中所学到的知识呢?从那里,JIT可以照常工作,进行重新优化。关闭时,该代码可以再次保存,并在下一次运行中用作新的起点。
Puce 2012年

1
@Puce我能想到的唯一原因是AFAIK您无法从运行优化的代码获得任何分析统计信息。因此,您将无处改善……
maaartinus 2014年

1
我个人可以选择“仅保留运行之间的JIT分析信息”选项,并带有所有警告,“只有在完全相同的JVM,相同的数据等情况下,否则它会被忽略”。关于为什么尚未实现这一点,我希望持久性和验证JIT种子数据的额外复杂性太大,无法从其他项目中获取资源。考虑到在此和Java 8 lambda + streams之间进行选择,我宁愿使用后者。
托尔比约恩Ravn的安德森

25

甲骨文的JVM确实可以做到这一点-引用甲骨文,

编译器可以利用Oracle JVM的类解析模型来有选择地在数据库调用,会话或实例之间持久保存已编译的Java方法。当已知Java代码在语义上没有改变时,这种持久性避免了跨会话或实例进行不必要的重新编译的开销。

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


8
因为其他复杂的JVM并没有方便的大型企业RDBMS将内容存储在:)
skaffman 2010年

哇!这意味着编译有时会被缓存。这是个好消息!
Sandeep Jindal

IBM的J9也有记录。
user314104 2014年

9
请注意,此Oracle JVM是Oracle数据库内部的一个,而不是购买Sun时Oracle获得的下载。
托尔比约恩Ravn的安德森



0

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

  • Java的想法是在任何地方都可以编写一次即可运行的语言,将预编译的内容放到类文件中有点违反了这种想法(因为实际上字节码仍然存在,所以只有“一种”)
  • 这会增加类文件的大小,因为您将在同一时间多次使用同一代码,尤其是当您碰巧在多个不同的JVM下运行同一程序时(当您将不同的版本视为不同的JVM时,这并不罕见)。真的必须做)
  • 类文件本身可能不可写(尽管很容易检查)
  • JVM优化部分基于运行时信息,而其他运行则可能不适用(尽管它们仍应提供一些好处)

但是我确实在猜测,正如您所看到的,我真的不认为我的任何原因都是真正的阻碍。我认为Sun只是不将这种支持作为优先事项,也许我的第一个理由很接近事实,因为习惯性地这样做可能还会导致人们认为Java类文件确实需要为每个VM使用单独的版本,而不是跨平台。

我的首选方式实际上是拥有一个单独的字节码到本机的转换器,您可以使用它事先明确地执行类似的操作,创建为特定VM显式构建的类文件,其中可能包含原始字节码,以便您也可以在不同的VM上运行。但这可能来自于我的经验:我主要从事Java ME,Java编译器在编译方面并不明智,这确实让我很受伤。


1
实际上,在类文件中有一个地方,就是原来的意图(将JIT编辑的代码作为属性存储在类文件中)。
TofuBeer

@TofuBeer:感谢您的确认。我怀疑可能是这种情况(这是我会做的),但不确定。编辑以将其删除为可能的原因。
JaakkoK 2010年

我认为您的最后一个要点击中了头部。可以解决其他问题,但我认为最后一部分是不能保留JITed代码的主要原因。
Sasha Chedygov,2010年

1
关于显式字节码到本机编译器的最后一段是您当前在.NET中使用NGEN(msdn.microsoft.com/en-us/library/6t9t5wcf ( VS.71 ) .aspx)所具有的内容。
R. Martinho Fernandes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.