【问题标题】:Just in Time Compilation - Storing vs Doing always [duplicate]及时编译 - 存储与始终执行[重复]
【发布时间】:2012-07-24 01:09:13
【问题描述】:

可能重复:
Why doesn't the JVM cache JIT compiled code?

我知道JIT编译是使用热点机制编译成本机代码,它可以非常非常快,因为它是对操作系统、硬件等的优化。

我的问题是,为什么 Java 不将 JIT 编译的代码存储在文件中的某处并为将来的目的使用相同的代码?这也可以减少“初始预热”时间。

请让我知道我在这里缺少什么。

补充我的问题: 为什么 Java 不将完整的代码编译为原生代码并始终使用它(对于特定的 JVM、操作系统、平台)?为什么选择 JIT?

【问题讨论】:

    标签: java performance jvm jit jvm-hotspot


    【解决方案1】:

    我自己也问过这个问题。我得到的印象是很难做到正确并避免拥有包含过期代码的商店。

    解决此问题的一种方法是发送-XX:+PrintCompilation 并编写一个简短的预热例程来预热这些方法。

    【讨论】:

      【解决方案2】:

      虽然可以保证您将始终使用 JVM,但不能保证您将始终使用同一个 JVM。热点优化代码仅对您的机器有效。

      对于 Java,不能保证代码是 JVM 本地的。小程序就是一个很好的例子,Webstart 也说明了这一点。一个通用的“保持优化”只会在很少运行的代码中弄乱缓存,并在哪里保持优化的扩展产生问题。

      在知道磁盘缓存保留多长时间方面也会产生相当大的困惑,而且您是否必须重新编译“类”文件来验证缓存是否用于类的正确“释放”文件? Java 没有相同类文件指示符的“此版本”,但可选的串行版本 uid 除外。

      也许有一种解决方法,方法是检查类文件的总和并将其放置在已编译类的字段中,但我不想考虑负责扫描所有缓存的机器特定代码、构建表的 JVM 的启动时间,干预类加载器,并使用优化代码检查加载类的校验和。

      【讨论】:

        【解决方案3】:

        如果我没记错的话,已经尝试过缓存和共享 JIT 编译的代码,发现不是一个好主意。

        一方面,现代 HotSpot JIT 编译器在当前 CPU 模型和当前执行的使用模式的上下文中生成和优化代码。如果要缓存编译后的代码,那么代码很可能不是最优的。

        另一方面,显然存在各种欺骗性的技术问题。例如,缓存的代码成为潜在的安全漏洞,例如,代码区域需要由共享它的所有应用程序/用户写入。但这意味着一个用户可能会干扰另一个用户的应用程序的运行。

        【讨论】:

        • 为什么缓存的优化代码必须在用户之间共享?通常用户主目录中有一个.java目录来存储这些数据。
        • 我猜,根据以前运行收集的数据优化的代码很可能比未优化的代码更好。
        • @Puce - 如果存在优化不佳的代码会阻止 JVM 收集使用情况统计信息,或者 JIT 编译器无法尝试优化,则不会。这是一个复杂的问题领域,其中“直观明显”的事情不一定正确。
        • @Puce - “为什么缓存的优化代码必须在用户之间共享?” - 不需要。我提出这只是其中一个例子,为什么这在技术上很棘手......
        【解决方案4】:

        它存在于.Net(在许多方面类似于java),它被称为NGEN。所以我不明白为什么它不能在 java 中存在。

        我可以看到没有完成的两个原因:

        • Java 没有像 .net 那样用于其程序集的良好 ID 机制。但确实可以使用散列(在 jar 或类级别)。
        • 它主要(仅?)在应用程序启动时受益。从 JRE6 开始,启动速度变得更快。

        【讨论】:

          【解决方案5】:

          一些 JVM(比如 IBM 的)确实有“ahead of time shared JIT code”。这很难做到(正如其他答案所指出的那样),因为一个 JVM 一次使用的类文件可能与下次使用的类文件不同,即使它们具有相同的名称。因此,需要大量的逻辑来证明“我之前看到的 A 类和我现在的 A 类真的是一样的”。

          另一个问题是 JIT 代码通常包含特定于地址空间的值(例如:给定静态变量的地址,或另一个 JIT 方法的入口点),并且这些值可以(并且肯定会!)在每个 JVM 上发生变化调用,因此,在处理这些问题时必须小心。

          AOT 代码提供的性能优势是真实的,该功能非常值得根据情况使用。 (特别是:事情不会改变运行,等等 - 比如调用相同版本的应用服务器或 Eclipse,例如)

          【讨论】:

          • "因此需要大量的逻辑来证明“我之前看到的 A 类和我现在拥有的 A 类真的一样”。 -> 看看日期?
          • 所以是的,日期是第一件事,但通常还不够。举个简单的例子,2 As(具有相同的大小和时间戳)可能在 2 个不同的 jar 文件中,并且在运行之间搜索顺序颠倒了。您还假设具有基于文件的 .class 表示形式的简单类加载器(核心 JVM 本身在引导后实际上并不真正了解)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-11-15
          • 2012-10-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-22
          相关资源
          最近更新 更多