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

发布于 2024-08-16 19:09:09 字数 193 浏览 10 评论 0原文

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

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

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

The canonical JVM implementation from Sun applies some pretty sophisticated optimization to bytecode to obtain near-native execution speeds after the code has been run a few times.

The question is, why isn't this compiled code cached to disk for use during subsequent uses of the same function/class?

As it stands, every time a program is executed, the JIT compiler kicks in afresh, rather than using a pre-compiled version of the code. Wouldn't adding this feature add a significant boost to the initial run time of the program, when the bytecode is essentially being interpreted?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

内心激荡 2024-08-23 19:09:09

如果没有对 @MYYN 发布的链接进行剪切和粘贴,我怀疑这是因为 JVM 执行的优化不是静态的,而是基于数据模式和代码模式的动态优化。这些数据模式很可能会在应用程序的生命周期内发生变化,从而导致缓存的优化效果不佳。

因此,您需要一种机制来确定保存的优化是否仍然是最佳的,此时您不妨即时重新优化。

Without resorting to cut'n'paste of the link that @MYYN posted, I suspect this is because the optimisations that the JVM performs are not static, but rather dynamic, based on the data patterns as well as code patterns. It's likely that these data patterns will change during the application's lifetime, rendering the cached optimisations less than optimal.

So you'd need a mechanism to establish whether than saved optimisations were still optimal, at which point you might as well just re-optimise on the fly.

魔法唧唧 2024-08-23 19:09:09

Oracle 的 JVM 确实有记录这样做 - - 引用甲骨文,

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

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

Oracle's JVM is indeed documented to do so -- quoting Oracle,

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.

I don't know why all sophisticated VM implementations don't offer similar options.

红焚 2024-08-23 19:09:09

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

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

在非常高的层面上,其既定的目标是

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

希望这有帮助。

An updated to the existing answers - Java 8 has a JEP dedicated to solving this:

=> JEP 145: Cache Compiled Code. New link.

At a very high level, its stated goal is:

Save and reuse compiled native code from previous runs in order to
improve the startup time of large Java applications.

Hope this helps.

不即不离 2024-08-23 19:09:09

Excelsior JET 从 2.0 版开始就有一个缓存 JIT 编译器,早在2001。此外,它的 AOT 编译器可能会使用所有优化将缓存重新编译为单个 DLL/共享对象。

Excelsior JET has a caching JIT compiler since version 2.0, released back in 2001. Moreover, its AOT compiler may recompile the cache into a single DLL/shared object using all optimizations.

花间憩 2024-08-23 19:09:09

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

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

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

我更喜欢的方法实际上是拥有一个单独的字节码到本机翻译器,您可以使用它预先明确地执行类似的操作,创建为特定虚拟机显式构建的类文件,其中可能包含原始字节码,以便您也可以与不同的虚拟机一起运行。但这可能来自我的经验:我主要从事 Java ME,Java 编译器在编译方面并不更智能,这确实很糟糕。

I do not know the actual reasons, not being in any way involved in the JVM implementation, but I can think of some plausible ones:

  • The idea of Java is to be a write-once-run-anywhere language, and putting precompiled stuff into the class file is kind of violating that (only "kind of" because of course the actual byte code would still be there)
  • It would increase the class file sizes because you would have the same code there multiple times, especially if you happen to run the same program under multiple different JVMs (which is not really uncommon, when you consider different versions to be different JVMs, which you really have to do)
  • The class files themselves might not be writable (though it would be pretty easy to check for that)
  • The JVM optimizations are partially based on run-time information and on other runs they might not be as applicable (though they should still provide some benefit)

But I really am guessing, and as you can see, I don't really think any of my reasons are actual show-stoppers. I figure Sun just don't consider this support as a priority, and maybe my first reason is close to the truth, as doing this habitually might also lead people into thinking that Java class files really need a separate version for each VM instead of being cross-platform.

My preferred way would actually be to have a separate bytecode-to-native translator that you could use to do something like this explicitly beforehand, creating class files that are explicitly built for a specific VM, with possibly the original bytecode in them so that you can run with different VMs too. But that probably comes from my experience: I've been mostly doing Java ME, where it really hurts that the Java compiler isn't smarter about compilation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文