为什么JVM不预先编译整个程序,而不是逐个编译它?

2022-09-04 03:53:46

对于这个帖子,赫伯特·希尔德特写道:

重要的是要了解,一次将整个Java程序编译为可执行代码是不切实际的,因为Java执行各种运行时检查,这些检查只能在运行时完成。

他指的是什么运行时检查?

请解释逐个编译字节码的原因,而不是整个程序。


答案 1

可能有几个原因可以逐个编译它(这是我想到的前两个):

  1. 优化使用多次的代码,不是所有的代码都需要重新编译,而只是特定的部分。
  2. 通过网络获取类 - 有时您希望避免获取所有代码,因为它在带宽上花费。

我不知道这个网站是否准确,但我从中学到了很多东西:http://www.artima.com/insidejvm/ed2/index.html


答案 2

他说的是,在运行时将所有字节码编译为机器语言是不切实际的。您可以预编译所有内容,但这不是JIT采用的方法。

首先,不知道程序有多大。人们会在30分钟的启动中相当沮丧,因为它编译了它能找到的每个库(给定的Java程序不在单个文件中,它可以访问类路径中的所有内容)

另一方面,即使你告诉系统你的程序将使用哪些组件,也不知道你的程序有多少可以用于给定的运行 - 人们在30分钟的启动中运行一个参数由“--help”组成的命令行程序会更加沮丧。

最后,它可以通过在运行时进行编译来做一些很棒的技巧。使用如下方法:

public testMeh(int param) {
    if(param == 35) 
        do bunches of crap;
    else if (param > 5)
        do much more crap;
    else 
        return;
    }

编译器可以调用它一次或两次,并动态识别值 5 及以下只是返回。如果一直以 2 的值调用它,则可以将整个方法调用替换为 if (param != 2) testMeh(param);

这消除了对该数字的整个方法调用。稍后它可以发现,不调用该方法意味着某些成员变量无法更改,并且可以将代码的其他部分折叠为零。

如果你预编译东西,这简直很难。我的意思是,当你识别模式时,你可以在任何地方编写异常代码,但你的代码很快就会变成一场噩梦。

现在,如果你问为什么不在将整个程序编译成字节码时对其进行预编译 - 这是一个不同的问题,而不是引用所解决的问题 - 但你可以这样做。它已经完成了,效果很好。您可以牺牲可移植性和运行时灵活性,以缩短启动时间。


推荐