java jit编译时间升高_关于java:为什么JVM不缓存JIT编译代码?

本文讨论了Java JIT编译器在优化字节码后为何不将编译后的代码缓存到磁盘以供后续使用。虽然缓存可以减少启动时间,但JVM的动态优化特性使得静态缓存可能不适用于所有情况。不同JVM实现如Oracle和IBM的J9提供了缓存选项,但并非所有JVM都支持。Java 8引入了JEP 145来缓存已编译代码以提升启动时间。
摘要由CSDN通过智能技术生成

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

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

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

+1好问题

讨论此问题的线程:javalobby.org/forums/thread.jspa?threadID=15812

但是,一个不太可能引起肯定性答案的问题。

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

感谢大家的好评! 所有答案都是同等有效的,因此我与社区一起进行了这个……

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

Java 9中添加了初始通用支持。

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

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

...或者您可以像Oracle的JVM一样提供持久性作为一种选择-使高级程序员能够在他们只知道模式没有改变的情况下,在他们的责任下,优化他们的应用程序性能。为什么不?!

因为它可能不值得。如果SUN,IBM和BEA都不认为它们的性能JVM值得,那么这将是一个很好的理由。也许他们的RT优化比Oracle更快,这就是Oracle对其进行缓存的原因。

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

@Puce我能想到的唯一原因是AFAIK您无法从运行优化的代码获得任何分析统计信息。所以你没有办法改善...

我个人可以选择"仅保留运行之间的JIT分析信息"选项,并带有所有警告,"仅在完全相同的JVM,相同的数据等情况下,否则将被忽略"。关于为什么尚未实现,我希望持久性和验证JIT种子数据的额外复杂性太大,无法从其他项目中获取资源。给定此选项与Java 8 lambda + streams Id之间的选择,宁可使用后者。

@ThorbjrnRavnAndersen以及完全相同的os和cpu,不是吗?我认为而不是JVM,因为代码已经被编译为本地代码,所以操作系统和CPU应该很重要。

@KorayTugay不一定。我正在考虑的分析信息是"经常调用此方法,内联它!",这是对JIT编译器的提示。每次运行都会生成实际的机器代码-这是您正在优化的预热阶段。

@ThorbjrnRavnAndersen但是问题是关于缓存JIT编译的代码。而且JIT编译的代码是体系结构/操作系统特定的。

@KorayTugay ...在共享文件系统上,这将真的很令人兴奋。我可以想象整个事情都是一场噩梦。

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

the compiler can take advantage of

Oracle JVM's class resolution model to

optionally persist compiled Java

methods across database calls,

sessions, or instances. Such

persistence avoids the overhead of

unnecessary recompilations across

sessions or instances, when it is

known that semantically the Java code

has not changed.

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

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

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

IBM的J9也被记录为这样做。

请注意,此Oracle JVM是Oracle数据库内部的一个,而不是Oracle在购买Sun时获得的下载。

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

=> JEP 145:缓存已编译代码 s>。新链接。

在非常高的水平上,其既定目标是:

Save and reuse compiled native code from previous runs in order to

improve the startup time of large Java applications.

希望这可以帮助。

该功能尚未发布到最终版本。

链接断开。 ---

另请参阅(stackoverflow.com/questions/39394819)

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

是的,但是问题是关于规范的JVM,即Suns JVM。我很清楚,有几种针对Java以及其他缓存JVM的AOT编译器。

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

Java的想法是在任何地方都可以一次写入运行的语言,并且将预编译的内容放到类文件中有点违反了这种想法(因为实际上字节代码仍然存在,所以只有"一种")

这会增加类文件的大小,因为您会多次在其中拥有相同的代码,尤其是当您碰巧在多个不同的JVM下运行同一程序时(当您将不同的版本视为不同的JVM时,这并不罕见)。真的必须做)

类文件本身可能不可写(尽管检查起来很容易)

JVM优化部分基于运行时信息,而其他运行则可能不适用(尽管它们仍应提供一些好处)

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

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

实际上,在类文件中有一个地方可以用作原始目的(将JITed代码作为属性存储在类文件中)。

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

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

关于显式字节码到本机编译器的最后一段是您当前在.NET中使用NGEN(msdn.microsoft.com/zh-cn/library/6t9t5wcf(VS.71).aspx)的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值