据我所知,Java编译为Java字节码,然后可以由任何运行Java的机器解释其特定的CPU。 Java使用JIT来解释字节码,我知道这样做的速度非常快,但为什么语言设计者一旦检测到正在运行的特定机器,就不会静态编译成机器指令?是否每次都通过代码解释字节码?
答案 0 :(得分:19)
原始设计的前提是“编译一次运行”。因此,虚拟机的每个实现者都可以运行编译器生成的字节码。
在书Masterminds for Programming中,James Gosling解释说:
詹姆斯:没错。这些天我们都是 打败真正优秀的C和C ++ 编译器几乎总是。当你 转到动态编译器,你得到 编译器的两个优点 在最后一刻跑。一 你知道什么是芯片组吗? 你正在奔跑。这么多次 人们正在编译一块C 代码,他们必须编译它才能运行 关于通用x86的种类 建筑。几乎没有 你得到的二进制文件特别好 调整了他们中的任何一个。你下载了 Mozilla的最新版本,它会 几乎任何英特尔都可以运行 架构CPU。有很多 一个Linux二进制文件这很通用, 它是用GCC编译的 不是一个非常好的C编译器。
当HotSpot运行时,它确切地知道 你在运行什么芯片组。它 确切地知道缓存是如何工作的。它 确切知道内存层次结构 作品。它确切地知道所有的 管道互锁在CPU中工作。 它知道什么指令集 这个芯片有扩展。它 精确地优化什么机器 轮到你了。然后是另一半 是它实际上看到了 应用程序正在运行。它能够 有统计数据知道哪些 事情很重要。它能够 C编译器可以内联的东西 永远不会做。得到的东西 在Java世界中内联很漂亮 惊人。然后你抓住那个 存储管理的工作方式 现代垃圾收集者。有了 现代垃圾收集器,存储 分配非常快。
答案 1 :(得分:7)
Java 通常编译为机器指令;那就是即时(JIT)编译。但是,默认情况下,Sun的Java实现仅对经常运行的代码执行此操作(因此启动和关闭字节码,仅执行一次,仍然会被解释为防止JIT开销)。
答案 2 :(得分:5)
对于很多情况,字节码解释通常“足够快”。另一方面,编译相当昂贵。如果90%的运行时间花费在1%的代码中,那么编译1%并将其他99%单独留下来要好得多。
答案 3 :(得分:1)
静态编译可能会爆炸,因为您使用的所有其他库也需要一次写入(即字节码),包括所有依赖项。这可能会导致依赖关系的一系列编译可能会对您产生影响。仅将代码编译为(运行时)运行时发现它实际上需要编译的代码段是我认为的一般想法。可能有许多代码路径实际上没有遵循,特别是当库受到质疑时。
答案 4 :(得分:0)
动态编译的一个重要区别是它优化了代码库的运行方式。有一个选项-XX:CompileThreshold=
默认为10000。您可以减少这一点,以便更快地优化代码,但如果您运行复杂的应用程序或基准测试,您会发现减少此数字可能会导致代码更慢。如果你运行一个简单的基准测试,你可能会发现它没有任何区别。
动态编译优于静态编译的一个示例是内联“虚拟”方法,尤其是可以替换的方法。例如,JVM可以内联最多两个使用频繁的“虚拟”方法,这些方法可能位于编译调用者之后编译的单独jar中。被叫罐甚至可以从运行系统中移除,例如OSGi并添加或替换它的另一个jar。然后可以内联替换JAR的方法。这只能通过动态编译来实现。
答案 5 :(得分:0)
解释Java字节码是因为字节码可以跨各种平台移植.JVM是平台相关的,它将字节码转换并执行到该机器的特定指令集,无论它是Windows还是LINUX或MAC等......