我一直在弄清楚翻译的确切工作,搜索过并得出一些结论,只是希望能够让我更好地理解翻译工作的人来纠正它。
所以我所理解的是:
现在我仍然不清楚之间发生的子过程,即
还有一些问题:
解释器是一种将代码从高级语言转换为机器格式的软件程序。
不,那是编译器。 interpreter是一种计算机程序,它直接执行用语言编写的指令。这与将较高级语言转换为较低语言的编译器不同。 C编译器从C转换为汇编代码,汇编程序(另一种编译器)从汇编代码转换为机器代码 - 现代C编译器执行从C到机器代码的两个步骤。
在Java中,java编译器执行代码验证并从Java源转换为字节码类文件。它还执行许多小的处理任务,例如常量的预计算(如果可能),字符串的缓存等。
现在,java解释器的平台是运行它的JVM,所以基本上它将生成可以由JVM运行的代码。
JVM直接对字节码进行操作。 Java解释器与JVM紧密集成,它们不应该被视为单独的实体。正在发生的事情是大量的优化,其中字节码基本上是在运行中优化的。这使得称它只是一个翻译不足。见下文。
所以它需要字节码产生中间代码和目标机器代码并将其提供给JVM。
JVM正在进行这些翻译。
JVM轮流在实现或运行JVM的OS平台上执行该代码。
我宁愿说JVM使用字节码,优化的用户代码,包含java和本机代码的java库,以及OS调用来执行java应用程序。
现在我仍然不清楚在它们之间发生的子过程,即1.解释器产生中间代码。 2.然后优化解释的代码。 3.然后生成目标代码4.最后执行。
Java编译器生成字节码。当JVM执行代码时,步骤2-4在JVM内部的运行时发生。它与C(例如)非常不同,后者由不同的实用程序运行这些单独的步骤。不要将其视为“子进程”,将其视为JVM内部的模块。
单独的解释器负责生成目标代码吗?并执行它?
有点。根据定义,JVM的解释器读取字节码并直接执行它。但是,在现代JVM中,解释器与即时编译器(JIT)协同工作到generate native code on the fly,以便JVM可以更有效地执行代码。
此外,还有后处理“编译”阶段,它们在运行时分析生成的代码,以便通过内联常用代码块和其他机制来优化本机代码。这就是为什么JVM加载在启动时如此高的原因。它不仅加载在罐子和类文件中,而且它实际上是在运行中进行cc -O3
。
并且执行是否意味着它在JVM或底层操作系统中执行?
虽然我们讨论了执行代码的JVM,但这在技术上并不正确。一旦将字节码转换为本机代码,JVM和Java应用程序的执行就由CPU和其他硬件架构完成。
操作系统是完成所有过程和资源管理的基础,因此程序可以有效地共享硬件并高效执行。操作系统还为应用程序提供API,以便轻松访问磁盘,网络,内存以及其他硬件和资源。
1)解释器是一种将代码从高级语言转换为机器格式的软件程序。
不正确。解释程序是运行以某种语言表达的程序的程序,该程序不是计算机的本机机器代码。
在此过程中可能有一个步骤,其中源语言被解析并转换为中间语言,但这不是解释器的基本要求。在Java的情况下,字节码语言的设计使得既不需要解析也不需要不同的中间语言。
2)具体讲述java解释器,它以二进制格式获取代码(之前由java编译器从源代码翻译成字节码)。
正确。 “二进制格式”是Java字节码。
3)现在java解释器的平台是运行它的JVM,所以基本上它将生成可以由JVM运行的代码。
不正确。字节码解释器是JVM的一部分。解释器不在JVM上运行。字节码解释器不会产生任何东西。它只运行字节码。
4)所以它需要字节码产生中间代码和目标机器代码并将其提供给JVM。
不正确。
5)JVM轮流在实现或运行JVM的OS平台上执行该代码。
不正确。
真实的故事是这样的:
1 - 典型的字节码解释器可以将抽象堆栈帧和对象布局映射到涉及特定于目标的大小和偏移的具体映射。但要称之为“中间代码”是一个延伸。解释器实际上只是增强了字节码。
Java应用程序有两个主要步骤:编译和运行时。每个过程都有不同的功能和用途。两者的主要流程概述如下:
[com.sun.tools.javac][1]
执行,通常在tools.jar文件中找到,传统上在$ JAVA_HOME中 - 与java.jar等相同的位置。编译步骤:
[com.sun.tools.JCTree][3]
。总体思路是每个Expression和每个Statement都有一个java对象。在这个时间点,对于每个代表的实际“类型”知之甚少。在创建AST时唯一检查的是文字语法我会根据我创建DSL的经验回答。
编译C是因为您运行将源代码传递给gcc并在机器代码中运行存储的程序。
解释Python是因为您通过将程序源传递给解释器来运行程序。解释器读取源文件并执行它。
Java是两者的混合,因为您将Java文件“编译”为字节码,然后调用JVM来运行它。字节码不是机器码,需要由JVM解释。 Java位于C和Python之间,因为你无法做像“eval”这样的奇特事情(在运行时像在Python中一样评估代码块或表达式)。但是,Java具有C程序无法实现的反射能力。简而言之,Java运行时设计在纯编译语言和解释语言之间的中间层中,在性能和灵活性方面给出了两个单词中最好的(也是最差的)。
但是,Python也有一个虚拟机,它有自己的字节码格式。这同样适用于Perl,Lua等。这些解释器首先将源文件转换为字节码,然后它们解释字节码。
我一直想知道为什么这样做是必要的,直到我为模拟DSL制作了自己的解释器。我的解释器进行词法分析(打破令牌中的源),将其转换为抽象语法树,然后通过遍历它来评估树。为了软件工程,我使用了一些设计模式,而我的代码大量使用多态。与处理模仿真实计算机体系结构的有效字节码格式相比,这非常慢。如果我创建自己的虚拟机或使用现有的虚拟机,我的模拟会更快。例如,为了评估一个长数值表达式,将它转换为类似于汇编代码的东西要比处理抽象树的一个分支更快,因为它需要调用许多多态方法。
有两种执行程序的方法。
.c
上,它将编程语言中的文本(比如.exe
)解析为机器代码。然后可以独立于编译器执行此操作。可以通过将几个.c
文件编译为多个目标文件(中间产品),然后将它们链接到单个应用程序或库中来完成此编译。
.java
)并“立即”执行程序。使用java,这种方法有点混合/堆叠:java编译器javac
将.java
编译为.class
文件,并且可能在.jar
(或.war
,.ear
......)中编译。 .class文件由抽象堆栈机器的更抽象的字节代码组成。
然后,java运行时java
(调用JVM,java虚拟机或字节码解释器)可以执行.class / .jar。这实际上是java字节代码的解释器。
现在它还将运行时的字节代码(部分)转换为机器代码。这也称为即时编译器,用于字节代码到机器代码。
简而言之: - compiler
只创建代码; - interpreter
立即执行。
解释器将遍历解析命令/高级中间代码,并用一段代码解释每个命令。间接原则上很慢。