java编译到底有多精确?

java编译过程困惑

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

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

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

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

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

实际上,编译器本身就是一个本地可执行文件(因此是javac.exe)。 而且,它将源文件转换为字节码。 字节码是独立于平台的,因为它是针对Java虚拟机的。

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

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

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

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

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

这正是包装代码所做的。

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

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

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

它不是抽象语法树。 AST仅在编译时使用标记器和编译器来表示内存中的代码。 .class文件就像一个程序集,但对于JVM。 JVM反过来是一个抽象机器,它可以运行专门的机器语言 – 只针对虚拟机。 在最简单的情况下, .class文件与正常的程序集结构非常相似。 开始时声明所有静态variables,然后是一些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的内部读取器 (或标记器)读取您的文件并从中构build实际的AST。 所有的语法错误都来自这个阶段。

  • javac还没有完成它的工作。 当它具有AST时,真正的编译可以开始。 它使用访问者模式来遍历AST并parsing外部依赖关系,为代码添加含义(语义)。 成品保存为包含字节码的.class文件。

  • 现在是时候运行的事情。 你用.classfile的名字来调用java 。 现在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实现上。 这将使构build系统依赖于它。 如果切换到任何其他JDK(除了Sun以外的wiki列表5),则应更新上面的代码以反映更改(因为编译器不太可能驻留在com.sun.tools.javac包中)。 其他编译器可以用本地代码编写。

所以标准的方法是用JDK发布javac包装器。

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

你从哪里得到这些信息? javac可执行文件可以用任何编程语言编写,这是无关紧要的,重要的是它是一个将.java文件转换成.class文件的可执行文件。

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

  • 虚拟机启动
  • 加载类和接口

您还可以看看虚拟机规范 ,其中包括:

  • class文件格式
  • Java虚拟机指令集
  • 编译Java虚拟机

编译器javac.exe是一个.exe文件。 这个.exe文件到底是什么? 是不是用java编写的java编译器,那么怎么会有执行它的.exe文件?

Java编译器(至less是Sun / Oracle JDK附带的)确实是用Java编写的。 javac.exe只是一个启动程序,它处理命令行参数,其中一些传递给运行编译器的JVM,另一些传递给编译器本身。

如果编译器编写的代码是java,那么编译器的代码是如何在编译阶段执行的,因为它的工作就是执行java代码的jvm。 语言本身如何编译自己的语言代码? 这一切似乎像鸡和鸡蛋问题给我。

许多(如果不是大多数)编译器是用他们编译的语言编写的。 显然,在某个早期阶段,编译器本身必须由其他东西编译,但是在“引导”之后,任何新版本的编译器都可以被旧版本编译。

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

Java虚拟机规范中描述了类文件格式的详细信息。

那么,javac和jvm通常是本地的二进制文件。 他们用C或者其他什么书写。 在Java中编写它们当然是可能的,只是你需要一个本地版本。 这被称为“引导捆绑”。

有趣的事实:大多数编译为本地代码的编译器都是用自己的语言编写的。 但是,他们都必须先用另一种语言(通常是C)编写本地版本。 相比之下,第一个C编译器是用汇编语言编写的。 我认为第一个汇编程序是用机器码写的。 (或者, 使用蝴蝶 ;)

.class文件是由javac生成的字节码。 它们不是文本的,它们是类似于机器代码的二进制代码(但是具有不同的指令集和架构)。

在运行时,jvm有两个select:它可以解释字节码(伪装成CPU本身),也可以JIT(即时)将其编译为本地机器码。 后者当然更快,但更复杂。

.class文件包含有点类似于非常高级的Assembly的字节码。 编译器可以很好地用Java编写,但是JVM必须被编译为本地代码以避免鸡/蛋问题。 我相信它是用C语言编写的,标准库的底层也是如此。 当JVM运行时,它会执行即时编译,将该字节码转换为本地指令。

Windows在安装Java运行时之前不知道如何调用Java程序,Sunselect了收集参数的本地命令,然后调用JVM而不是将jar-suffix绑定到Java引擎。

简短说明

在一个文本编辑器中编写代码,将其保存为编译器可以理解的格式 – “.java”文件扩展名, javac (java编译器)将其转换为“.class”格式文件(字节代码 – 类文件)。 JVM在它所在的操作系统上执行.class文件。

长的解释

永远记得java不是操作系统所能识别的基础语言。 Java源代码被称为Java虚拟机(JVM)的翻译器解释为操作系统。 JVM不能理解你在编辑器中编写的代码,它需要编译代码。 这是编译器进入画面的地方。

每一个电脑进程都沉迷于内存操作。 我们不能在文本编辑器中编写代码并编译它。 我们需要把它放在计算机的内存中,即在编译之前保存它。

javac(java编译器)如何将保存的文本识别为要编译的文本? – 我们有一个单独的文本格式,编译器可以识别,即.java 。 将该文件保存为.java扩展名,编译器将会识别它并在请求时进行编译。

编译时会发生什么? 编译器是第二个翻译者(不是技术术语),它将用户理解的语言(Java)翻译成JVM理解的语言(字节代码 – .class格式)。

编译后会发生什么? 编译器生成JVM可以理解的.class文件。 然后程序被执行,即.class文件由操作系统上的JVM执行。

你应该知道的事实

1)Java不是多平台,它是平台独立的

2)JVM是使用C / C ++开发的 。 人们称Java比C / C ++慢的原因之一

3)Java字节码(.class)是“汇编语言” ,是JVM理解的唯一语言。 在编译或生成的字节代码上生成.class文件的任何代码都可以在JVM上运行。

编译器最初是用C ++编写的,我认为它仍然是(为什么你认为编译器也是用Java编写的?)。 javac.exe只是编译器的C / C ++代码。

作为一个方面,你可以用java编写编译器,但是你是对的,你必须避免鸡和鸡蛋的问题。 要做到这一点,你通常会编写一个或多个类似C的引导工具来编译编译器。

.class文件包含字节码,javac编译过程的输出,这些是告诉JVM要做什么的指令。 在运行时,这些字节码已被转换为本地CPU指令(机器码),以便它们可以在JVM下的特定硬件上执行。

为了使这一点复杂化,JVM还优化和caching从字节码产生的机器码,以避免重复翻译它们。 这被称为JIT编译,并在程序运行和字节码解释时发生。

  1. .java文件
  2. 编译器(JAVA BUILD)
  3. 的.class(字节码)
  4. JVM(系统软件通常用“C”构build)
  5. 操作平台
  6. 处理器