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编译,并在程序运行和字节码解释时发生。
- .java文件
- 编译器(JAVA BUILD)
- 的.class(字节码)
- JVM(系统软件通常用“C”构build)
- 操作平台
- 处理器
- 在每个编辑中禁用显示“输出窗口”
- .NET 4.0在CI服务器上生成问题
- 了解Crockford的Object.create垫片
- 我可以在不安装Visual Studio的情况下使用mstest.exe吗?
- iOS – UIBarButtonItem标识符 – 创build“设置”齿轮button的选项
- Web开发人员 – 在本地机器上还是在远程主机上进行开发更好?
- Android Build失败 – java.lang.IllegalArgumentException:已经添加:Lcom / google / api / client / escape / CharEscapers;
- 有没有办法编程滚动滚动视图到特定的编辑文本?
- Golang在子目录中进行testing