java编译如何发生?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (33)

由java编译过程困惑

OK我知道这一点:我们编写Java源代码,独立于平台的编译器将其转换为字节码,然后依赖于平台的jvm将其转换为机器码。

所以从一开始,我们就编写java源代码。编译器javac.exe是一个.exe文件。这个.exe文件到底是什么?是不是用java编写的java编译器,那么怎么会有执行它的.exe文件?如果编译器代码编写为java,那么在编译阶段如何执行编译器代码,因为它是jvm执行java代码的工作。语言本身如何编译自己的语言代码?这一切似乎对我来说是鸡和鸡蛋的问题。

现在.class文件包含什么内容?它是一种文本形式的抽象语法树,它是表格信息,它是什么?

任何人都可以告诉我关于我的java源代码如何在机器代码中转换的清晰和详细的方式。

提问于
用户回答回答于

好的,我知道这一点:我们编写java源代码,独立于平台的编译器将其转换为字节码,

实际上,编译器本身工作作为本机的可执行文件(文件javac.exe因此)。而且,它将源文件转换为字节码。字节码与平台无关,因为它的目标是Java虚拟机。

那么依赖于平台的jvm会将其转换为机器码。

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

所以从一开始,我们就编写java源代码。编译器javac.exe是一个.exe文件。这个.exe文件到底是什么?是不是用java编写的java编译器,那么怎么会有执行它的.exe文件?

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

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

这正是包装代码所做的。

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

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

现在.class文件包含什么内容?它是一种文本形式的抽象语法树,它是表格信息,它是什么?

它不是抽象语法树。AST仅由编译器和编译器在编译时用来表示内存中的代码。.class文件就像一个程序集,但对于JVM。JVM反过来是一个抽象机器,它可以运行专门的机器语言 - 只针对虚拟机。在最简单的情况下,.class文件与正常装配结构非常相似。在开始时声明了所有的静态变量,然后是一些extern函数签名表,最后是机器码。

如果你真的好奇你可以使用“javap”实用程序挖掘classfile。以下是调用的示例(混淆)输出javap -c Main

0:   new #2; //class SomeObject
3:   dup
4:   invokespecial   #3; //Method SomeObject."<init>":()V
7:   astore_1
8:   aload_1
9:   invokevirtual   #4; //Method SomeObject.doSomething:()V
12:  return

所以你应该有一个想法已经是真的。

任何人都可以告诉我关于我的java源代码如何在机器代码中转换的清晰和详细的方式。

我认为现在应该更加清楚,但这里有简短的总结:

  • 你调用javac指向你的源代码文件。javac 的内部读取器(或标记器)读取您的文件并从中构建实际的AST。所有的语法错误都来自这个阶段。
  • javac还没有完成它的工作呢。当它具有AST时,真正的编译可以开始。它使用访问者模式来遍历AST并解析外部依赖关系,为代码添加含义(语义)。成品保存为.class包含字节码的文件。
  • 现在是时候运行这个东西了。您java使用.classfile的名称进行调用。现在JVM再次启动,但解释您的代码。JVM可能会或可能不会将您的抽象字节码编译为本地程序集。如果需要,Sun的HotSpot编译器和Just In Time编译可能会这样做。正在运行的代码不断由JVM进行分析,并在满足某些规则时重新编译为本机代码。最常见的热门代码是第一个本地编译的。

没有javac人将不得不调用编译器使用类似这样的事情:

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

正如你可以看到它调用了Sun的私有API,所以它必然会与Sun JDK实现绑定。它会使构建系统依赖于它。如果切换到任何其他JDK(除Sun之外的wiki列表5),则应更新上面的代码以反映更改(因为编译器不太可能驻留在com.sun.tools.javac包中)。其他编译器可以用本地代码编写。

所以标准的方法是javac用JDK提供包装。

用户回答回答于

是不是用java编写的java编译器,那么怎么会有执行它的.exe文件?

你从哪里得到这些信息?该javac可执行文件可以写在任何编程语言,它是无关紧要的,所有重要的是,它是一个可执行文件,打开.java文件到.class文件。

有关.class文件二进制规范的详细信息,您可能会发现Java语言规范中的这些章节很有用(尽管可能有点技术性):

您还可以查看虚拟机规范,其中涵盖:

扫码关注云+社区