当前位置: 首页 > 知识库问答 >
问题:

关于传统解释器、编译器和JIT编译器/解释器的澄清

秦博延
2023-03-14

我正在学习Java,下面的事情让我有点困惑。我的理解是:

>

  • Java编译器→Java编译器只是将. java程序转换为. class文件,这意味着将我们的源代码转换为字节码(它是虚拟机(JVM)的操作代码列表,使Java平台独立)。

    Java解释器→只是“解释”代码,而不是将其转换为本机机器代码。它将字节码的每一条指令作为命令逐一执行并执行,而不管同一条指令发生多少次。这就是为什么它很慢,Java引入了JIT概念。

    JIT编译器→这也在执行时发挥作用。即时编译器能够通过缓存已翻译代码块的结果来提高性能——相比之下,每次发生时只需重新评估字节码中的每一行或操作数。

    现在我有几个问题:

    >

  • 由于我的物理处理器只理解本机代码,如何使用JVM的解释器执行Java程序?解释器不会将字节码转换为本机代码。除非有人将机器代码放入内存,否则物理处理器将无法执行它。

    假设解释器也以某种方式将字节码转换为本机代码,那么“带缓存的代码块执行(JIT)和逐行执行(解释器)”是JIT和解释器的唯一区别?

    如果JIT编译器在执行时将字节码转换为本机代码(用于执行程序),为什么Java不使用提前编译?生成依赖于JVM的字节码(这反过来又使Java平台独立)后,我们可以将其带到要执行它的目标机器上,并将其转换为本机代码(创建一个.exe或.out文件,就像C编译一样)。这是可能的,因为我们在每个系统上都有一个特定的JVM。这将比使用JIT编译快得多,因为编译和加载程序需要一些时间。它仍然是独立于平台的,只需分发字节码(在字节码最终转换为机器码之前生成)。

  • 共有2个答案

    缪阎宝
    2023-03-14

    >

    对差不多吧。

    正如您所提到的,Java被吹捧为“编译一次,在任何地方运行”。所以字节码是实现这一promise的重要特性。当它到达您的计算机时,它不会被编译的原因是一个实际的原因:编译很慢。通常,它发生在软件开发人员那里。如果您启动的每个Java应用程序都是第一次编译的,那么您需要等待一段时间。

    由于大多数程序没有完全运行(有没有使用的分支,您从不选择的菜单项等),因此编译需要的部分通常更快。它还节省了磁盘空间,否则您的计算机上的每个程序都会有两个副本。

    也就是说,您并不是第一个对此感到奇怪的人,事实上,有些人用Java编写程序,但使用编译器从中实际生成可执行文件。Java(-to native)编译器已经存在,但它们不是常见的用例,因为当时很多人都使用可移植的C或C。

    萧凡
    2023-03-14

    免责声明:对所有这些都持怀疑态度;这太简单了。

    1: 您是正确的,因为计算机本身不理解代码,这就是为什么需要JVM本身。让我们假设XY的意思是“在堆栈上添加最上面的两个元素并推送结果”。然后,JVM将实现如下内容:

    for(byte bytecode : codeToExecute) {
        if (bytecode == XX) {
            // ...do stuff...
        } else if (bytecode == XY) {
            int a = pop();
            int b = pop();
            push(a+b);
        } else if (bytecode == XZ) {
            // ...do stuff...
        } // ... and so on for each possible instruction ...
    }
    

    JVM在计算机的本机机器代码中实现了每一条指令,并从本质上查找每一块字节码以了解如何执行它。通过JIT代码,可以通过省略此解释(即查找每个指令应该如何处理)来实现较大的加速。以及优化。

    2: JIT并没有真正运行代码;一切仍在JVM中运行。基本上,JIT会在适当的时候将字节码块转换为机器码。当JVM遇到它时,它会想:“哦,嘿,这已经是机器代码了!太好了,现在我不必仔细检查它的每个字节,因为CPU可以自己理解它!我只需要把它抽出来,一切都会神奇地自行工作!”。

    3:是的,可以通过这种方式预编译代码以避免解释和JITting的早期开销。但是,这样做会失去一些非常有价值的东西。您看,当JVM解释代码时,它还会保存有关所有内容的统计数据。然后当它JIT代码时,它知道不同部分的使用频率,允许它在重要的地方对其进行优化,以牺牲稀有内容为代价使常见内容更快,从而产生整体性能提升。

     类似资料:
    • 问题内容: 我正在学习Java,以下内容对我来说有些混乱。我了解的是: Java编译器 →Java编译器仅将程序转换为文件,这意味着将我们的源代码转换为字节码(这是使Java平台独立的虚拟机(JVM)的操作码的列表)。 Java Interpreter →仅“解释”代码,而 没有 将其转换为本地机器代码。它将一条字节码的每条指令作为一条命令一一执行并执行,而不管同一条指令出现多少次。这就是为什么它

    • 我对JIT编译器和解释器有些怀疑。从其定义开始: (翻译)来自维基百科: 在计算机科学中,解释器是一种计算机程序,它直接执行(即执行)用编程或脚本语言编写的指令,而无需事先将其批量编译成机器语言。解释器通常使用以下策略之一执行程序: 1)解析源代码并直接执行其行为 2)将源代码翻译成某种有效的中间表示形式,并立即执行该表示形式 3)显式执行由编译器(解释器系统的一部分)生成的存储预编译代码[1]

    • 翻译的结果是什么?它会把高级语言变成汇编语言还是机器语言,即二进制代码? 如果是后者,这是否意味着解释语言与介绍集没有关系? 一种语言只能有一个口译员?是因为解释器不做任何优化,所以我们不需要找到更好的解释器吗?

    • 问题内容: 为什么我们说Java是一种编译和解释语言? (编译和解释)这样做有什么好处? 问题答案: Java在编译时被编译为中间的“字节码”。这与像C之类的语言在编译时被编译为机器语言相反。Java字节代码无法像编译的C代码那样直接在硬件上执行。相反,字节码必须在运行时由JVM(Java虚拟机)解释才能执行。像C这样的语言的主要缺点是,当编译该二进制文件时,该二进制文件将仅在一种特定的体系结构(

    • 那么,让我看看我是否明白了这一点。 > 当我们说编译器和解释器之间的区别时,解释器将高级指令翻译成中间形式,然后执行。[我认为编译器也将高级指令翻译成中间形式,但此刻它生成目标代码而不是执行它,对吗?] 解释器一次读取一条指令或一行的源代码,将该行转换为机器代码并执行它。[解释器本身不会将代码转换为机器代码,它会使用ist自己的预编译函数评估指令(在解析之后)。例如,高级语言中的Add表达式将使用

    • 在我参加的一个reactJS会议上,演讲者使用了一个术语转译器来进行一些代码转换/移植。当涉及到将语言代码转换为计算机系统/机器上的可运行形式时,我总是使用和听到术语编译器和解释器。转译器对我来说是新的。转译器与编译器或解释器有什么不同,为什么真的需要它?