编译器构造 java_编译器构造-java编译究竟如何进行?

好的,我知道这一点:我们编写Java源代码,与平台无关的编译器将其转换为字节码,

实际上,编译器本身就是本机可执行文件(因此为javac.exe)。 的确,它将源文件转换为字节码。 字节码是平台无关的,因为它针对Java虚拟机。

然后依赖于平台的jvm将其转换为机器代码。

不总是。 至于Sun的JVM,有两个jvm:客户端和服务器。 它们都可以但不必一定要编译为本机代码。

因此,从一开始,我们就编写Java源代码。 编译器javac.exe是.exe文件。 .exe文件到底是什么? Java编译器不是用Java编写的,那么为什么会有执行它的.exe文件呢?

此javac文件是包装的Java字节码。 这是为了方便-避免复杂的批处理脚本。 它启动JVM并执行编译器。

如果编写的编译器代码是java,那么在编译阶段如何执行编译器代码,因为jvm的工作是执行Java代码。

这正是包装代码的作用。

语言本身如何编译自己的语言代码? 对我来说,这似乎是鸡和鸡蛋的问题。

是的,乍一看令人困惑。 虽然,这不仅是Java的习惯用法。 Ada的编译器也是用Ada本身编写的。 它可能看起来像“鸡和鸡蛋的问题”,但实际上,这只是一个引导问题。

现在,.class文件到底包含什么? 它是文本形式的抽象语法树,还是表格信息,它是什么?

它不是抽象语法树。 AST仅由令牌生成器和编译器在编译时使用,以表示内存中的代码。 javac文件就像一个程序集,但用于JVM。 JVM又是一种抽象机器,可以运行专门的机器语言-仅针对虚拟机。 最简单的是,.class文件的结构与普通程序集非常相似。 首先声明所有静态变量,然后是一些外部函数签名表,最后是机器代码。

如果您真的很好奇,可以使用“ java”实用程序来深入研究类文件。 这是调用javac的示例(混淆)输出:

0: new #2; //class SomeObject

3: dup

4: invokespecial #3; //Method SomeObject."":()V

7: astore_1

8: aload_1

9: invokevirtual #4; //Method SomeObject.doSomething:()V

12: return

所以您应该已经有了一个真正的想法。

谁能告诉我有关我的Java源代码如何在机器代码中转换的清晰详细的方法。

我认为现在应该更清楚了,但这是简短的摘要:

您调用javac指向您的源代码文件。 javac的内部读取器(或令牌生成器)读取您的文件,并根据该文件构建实际的AST。 所有语法错误都来自此阶段。

javac尚未完成工作。 如果具有AST,则可以开始进行真正的编译。 它使用访问者模式遍历AST并解决外部依赖关系,以在代码中添加含义(语义)。 成品另存为包含字节码的.class文件。

现在该运行该东西了。 您使用.class文件的名称调用javac。 现在,JVM再次启动,但可以解释您的代码。 JVM可能会或可能不会将您的抽象字节码编译到本机程序集中。 如果需要,可以结合使用Sun的HotSpot编译器和即时编译。 如果满足某些规则,则JVM会不断对正在运行的代码进行概要分析,并重新编译为本机代码。 最常见的是,热代码是第一个本地编译的代码。

编辑:如果没有javac,则必须使用类似于以下的方法来调用编译器:

%JDK_HOME%/bin/java.exe -cp:myclasspath com.sun.tools.javac.Main fileToCompile

如您所见,它正在调用Sun的私有API,因此它已绑定到Sun JDK实现。 它将使构建系统依赖它。 如果切换到任何其他JDK(wiki列出的Sun之外的5个JDK),则应更新上述代码以反映所做的更改(因为编译器不太可能驻留在com.sun.tools.javac程序包中)。 其他编译器可以用本机代码编写。

因此,标准方法是使用JDK运送javac包装器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值