Sun 公司提供的标准 JVM 实现会对字节码进行高级优化,使得代码在多次运行后能够获得接近原生执行速度。
问题是,为什么不将这些编译后的代码缓存到磁盘上,在后续使用相同函数或类时进行使用呢?
目前情况是,每次程序运行时,JIT 编译器都需要重新启动,而不是使用预编译版本的代码。如果增加这个功能,那么在程序刚开始运行时,即在字节码被解释执行时,将会显著提升程序的初始运行时间。
Sun 公司提供的标准 JVM 实现会对字节码进行高级优化,使得代码在多次运行后能够获得接近原生执行速度。
问题是,为什么不将这些编译后的代码缓存到磁盘上,在后续使用相同函数或类时进行使用呢?
目前情况是,每次程序运行时,JIT 编译器都需要重新启动,而不是使用预编译版本的代码。如果增加这个功能,那么在程序刚开始运行时,即在字节码被解释执行时,将会显著提升程序的初始运行时间。
不需使用@MYYN发帖中的链接,我怀疑这是因为JVM执行的优化不是静态的,而是动态的,基于数据模式和代码模式。很可能这些数据模式会在应用程序生命周期内改变,从而使缓存的优化不够优化。
所以你需要一种机制来确定这些保存的优化是否仍然是最佳的,在这种情况下,你最好还是动态重新进行优化。
Oracle 的 JVM 的确有文档可以实现这个功能 -- 引用 Oracle 的说法,编译器可以利用 Oracle JVM 的类解析模型选择性地在数据库调用、会话或实例之间保持已编译的 Java 方法。这样的保持可以避免在已知语义上 Java 代码未更改时跨会话或实例不必要的重新编译开销。
我不知道为什么所有复杂的 VM 实现都不提供类似的选项。
针对现有答案的更新 - Java 8有一个专门解决这个问题的JEP:
=> JEP 145: 缓存已编译代码。 新链接。
在非常高的层面上,它所述的目标是:
保存和重用先前运行中生成的本机代码,以改进大型Java应用程序的启动时间。
希望这可以帮助到您。
我不知道实际原因,也没有参与JVM实现,但我可以想到一些合理的原因:
但我真的只是猜测,而且正如你所看到的,我认为我的任何理由都不是真正的难题。我认为Sun只是不认为这种支持是一个优先事项,也许我的第一个原因接近真相,因为习惯性地这样做可能会让人们认为Java类文件确实需要为每个VM单独版本,而不是跨平台。
我的首选方式实际上是拥有一个独立的字节码到本地代码的转换器,你可以使用它来显式地预处理某些内容,创建专为特定虚拟机构建的类文件,可能还包含原始字节码,这样你就可以在不同的虚拟机上运行。但这可能来自于我的经验:我一直在做 Java ME,Java 编译器在编译方面并不聪明,这让我很受伤。