如果 java 可以编译代码,为什么还要解释代码?
why does java interpret code if it can compile it?
在企业应用程序中,相同的代码运行数天而从未重新启动,并且如果代码被多次命中,即超过阈值时间,那么它无论如何都会被 jit 编译(大部分)所以我想问一开始为什么不编译它。我的意思是 jvm 工程师可以将代码编译为字节码以保持平台独立性并再编译一次机器码并且机器码在一般情况下和何时不应该更快满足被 jit 编译的要求,然后 jvm 可以使用所有分析信息和统计信息来增强机器代码并进行所有增强。这肯定会占用编译时间,但一般代码而不是每次执行时都被解释 simply.i。e 创建一个编译器,它可以编译并吹嘘它,以防某些方法变得很热。我在这里可能是错的,但这是一个奇怪的问题。
它是多种因素和设计选择的混合体。
Java 以字节码的形式交付,没有永久性工件依赖于平台。这是确保平台独立性的设计选择。 Android 做出了不同的选择,主要是因为它运行的平台受到更多限制。
解释代码比编译代码更快运行一次。
因此,要获得最佳性能和良好的启动时间。当您确定需要代码时,开始编译是高效的。编译在另一个线程中完成,二进制文件一准备好就使用。当代码使用频率足够高时,Hotspot 甚至会进行多次重复编译。它可以使用实际的动态运行时特性,因此二进制文件可以比任何仅具有静态信息的代码更快。
Java 运行大部分解释代码,因为大多数代码解释运行速度足够快,并且不需要招致本机编译的开销。 JIT (HotSpot) 引擎将优化频繁使用的代码,在这种情况下付出的努力是值得的。此外,它将优化 in context,这意味着即使某个变量在理论上可能会发生变化,它也不会在特定的命令序列中发生变化,因此该序列可以将其放入将其注册或保持为常量。当违反假设时,JIT 会将其放回解释模式。提前编译将失去运行时洞察力的所有优势。 Java 的方法实际上生成的代码比 C++ 等编译语言所能实现的更紧凑、更高效。
编译优化非常昂贵。查看大型 C 项目(例如 firefox、linux 内核)的编译时间,尤其是 link 时间优化。
JIT 还针对目标平台进行编译,即它们尝试使用它们可以支持的所有可用指令进行编译,这意味着您无法分发编译后的代码。
现在考虑 JIT 执行推测性优化(基于分析),这可能会出错并需要退出。如果仅编译是一个选项,则此代码将无法继续 运行 直到重新编译。使用解释器,它可以继续执行导致紧急救援的不常见代码路径。
您还必须记住,某些优化是特定于工作负载的,即(坏的)测试工作负载可能会执行与实际工作负载不同的代码路径,因此在对其进行概要分析后会受益于不同的编译方式运行时间。
而且并非所有应用程序都是长期 运行ning 守护进程。有些东西启动 JVM 以执行单个任务,然后在完成后退出。
还要考虑很多代码只有 运行 一次,例如在应用程序启动或关闭期间。
所有这些因素导致了为什么 一些 JVM 默认使用解释器 + 编译器的组合。由于不同的技术权衡,其他人可能只使用 AOT 编译代码或只使用解释器,但它们通常不会更快。
在企业应用程序中,相同的代码运行数天而从未重新启动,并且如果代码被多次命中,即超过阈值时间,那么它无论如何都会被 jit 编译(大部分)所以我想问一开始为什么不编译它。我的意思是 jvm 工程师可以将代码编译为字节码以保持平台独立性并再编译一次机器码并且机器码在一般情况下和何时不应该更快满足被 jit 编译的要求,然后 jvm 可以使用所有分析信息和统计信息来增强机器代码并进行所有增强。这肯定会占用编译时间,但一般代码而不是每次执行时都被解释 simply.i。e 创建一个编译器,它可以编译并吹嘘它,以防某些方法变得很热。我在这里可能是错的,但这是一个奇怪的问题。
它是多种因素和设计选择的混合体。
Java 以字节码的形式交付,没有永久性工件依赖于平台。这是确保平台独立性的设计选择。 Android 做出了不同的选择,主要是因为它运行的平台受到更多限制。
解释代码比编译代码更快运行一次。 因此,要获得最佳性能和良好的启动时间。当您确定需要代码时,开始编译是高效的。编译在另一个线程中完成,二进制文件一准备好就使用。当代码使用频率足够高时,Hotspot 甚至会进行多次重复编译。它可以使用实际的动态运行时特性,因此二进制文件可以比任何仅具有静态信息的代码更快。
Java 运行大部分解释代码,因为大多数代码解释运行速度足够快,并且不需要招致本机编译的开销。 JIT (HotSpot) 引擎将优化频繁使用的代码,在这种情况下付出的努力是值得的。此外,它将优化 in context,这意味着即使某个变量在理论上可能会发生变化,它也不会在特定的命令序列中发生变化,因此该序列可以将其放入将其注册或保持为常量。当违反假设时,JIT 会将其放回解释模式。提前编译将失去运行时洞察力的所有优势。 Java 的方法实际上生成的代码比 C++ 等编译语言所能实现的更紧凑、更高效。
编译优化非常昂贵。查看大型 C 项目(例如 firefox、linux 内核)的编译时间,尤其是 link 时间优化。
JIT 还针对目标平台进行编译,即它们尝试使用它们可以支持的所有可用指令进行编译,这意味着您无法分发编译后的代码。
现在考虑 JIT 执行推测性优化(基于分析),这可能会出错并需要退出。如果仅编译是一个选项,则此代码将无法继续 运行 直到重新编译。使用解释器,它可以继续执行导致紧急救援的不常见代码路径。
您还必须记住,某些优化是特定于工作负载的,即(坏的)测试工作负载可能会执行与实际工作负载不同的代码路径,因此在对其进行概要分析后会受益于不同的编译方式运行时间。
而且并非所有应用程序都是长期 运行ning 守护进程。有些东西启动 JVM 以执行单个任务,然后在完成后退出。
还要考虑很多代码只有 运行 一次,例如在应用程序启动或关闭期间。
所有这些因素导致了为什么 一些 JVM 默认使用解释器 + 编译器的组合。由于不同的技术权衡,其他人可能只使用 AOT 编译代码或只使用解释器,但它们通常不会更快。