Sun的规范JVM实现对字节码进行了一些相当复杂的优化,以在代码运行几次后获得接近本机的执行速度。
问题是,为什么不将编译后的代码缓存到磁盘上以供以后使用同一功能/类时使用?
就目前而言,每次执行程序时,JIT编译器都会重新启动,而不是使用代码的预编译版本。当本质上解释字节码时,是否添加此功能不会大大提高程序的初始运行时间?
Sun的规范JVM实现对字节码进行了一些相当复杂的优化,以在代码运行几次后获得接近本机的执行速度。
问题是,为什么不将编译后的代码缓存到磁盘上以供以后使用同一功能/类时使用?
就目前而言,每次执行程序时,JIT编译器都会重新启动,而不是使用代码的预编译版本。当本质上解释字节码时,是否添加此功能不会大大提高程序的初始运行时间?
Answers:
我不求助于@MYYN发布的链接的'n'paste,我怀疑这是因为基于数据模式和代码模式,JVM执行的优化不是静态的而是动态的。这些数据模式可能会在应用程序的生命周期内发生变化,从而使缓存的优化效果不佳。
因此,您需要一种机制来确定所保存的优化是否仍然是最佳的,这时您可能还需要即时进行优化。
甲骨文的JVM确实可以做到这一点-引用甲骨文,
编译器可以利用Oracle JVM的类解析模型来有选择地在数据库调用,会话或实例之间持久保存已编译的Java方法。当已知Java代码在语义上没有改变时,这种持久性避免了跨会话或实例进行不必要的重新编译的开销。
我不知道为什么所有复杂的VM实现都没有提供类似的选项。
现有答案的更新-Java 8具有致力于解决此问题的JEP:
=> JEP 145:缓存编译代码。新链接。
在非常高的水平上,其既定目标是:
保存并重用以前运行时编译的本机代码,以缩短大型Java应用程序的启动时间。
希望这可以帮助。
Excelsior JET自2001年发布2.0版以来就具有缓存JIT编译器。此外,它的AOT编译器可以使用所有优化将缓存重新编译为单个DLL /共享对象。
我不知道实际原因,没有以任何方式参与JVM实现,但是我可以想到一些合理的原因:
但是我确实在猜测,正如您所看到的,我真的不认为我的任何原因都是真正的阻碍。我认为Sun只是不将这种支持作为优先事项,也许我的第一个理由很接近事实,因为习惯性地这样做可能还会导致人们认为Java类文件确实需要为每个VM使用单独的版本,而不是跨平台。
我的首选方式实际上是拥有一个单独的字节码到本机的转换器,您可以使用它事先明确地执行类似的操作,创建为特定VM显式构建的类文件,其中可能包含原始字节码,以便您也可以在不同的VM上运行。但这可能来自于我的经验:我主要从事Java ME,Java编译器在编译方面并不明智,这确实让我很受伤。