nas*_*ash 59 java compiler-construction jvm
困惑的java编译过程
好吧我知道这个:我们编写java源代码,平台独立的编译器将其转换为字节码,然后依赖于平台的jvm将其转换为机器代码.
所以从一开始,我们编写java源代码.编译器javac.exe是一个.exe文件.这个.exe文件究竟是什么?是不是用java编写的java编译器,那怎么会有执行它的.exe文件呢?如果编译的代码是java,那么编译器代码是如何在编译阶段执行的,因为它是jvm执行java代码的工作.语言本身如何编译自己的语言代码?这对我来说似乎都是鸡和蛋的问题.
现在.class文件到底包含什么?它是文本形式的抽象语法树,是表格信息,它是什么?
任何人都能告诉我有关如何在机器代码中转换我的java源代码的清晰而详细的方法.
Rek*_*kin 60
好吧我知道这个:我们编写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仅在编译时由tokenizer和编译器用于表示内存中的代码..class
文件就像一个程序集,但对于JVM.反过来,JVM是一个可以运行专用机器语言的抽象机器 - 仅针对虚拟机.在最简单的情况下,.class
文件具有与正常装配非常相似的结构.在开始时声明所有静态变量,然后是一些外部函数签名表,最后是机器代码.
如果你真的很好奇你可以使用"javap"实用程序挖掘类文件.以下是调用的示例(模糊处理)输出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
Run Code Online (Sandbox Code Playgroud)
所以你应该知道它到底是什么.
任何人都能告诉我有关如何在机器代码中转换我的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
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样,它正在调用Sun的私有API,因此它必然会受到Sun JDK的实现.它会使构建系统依赖于它.如果切换到任何其他JDK(wiki列出除Sun之外的5个),则应更新上面的代码以反映更改(因为编译器不太可能驻留在com.sun.tools.javac包中).其他编译器可以用本机代码编写.
所以标准的方法是javac
使用JDK 运送包装器.
Mic*_*rdt 11
编译器javac.exe是一个.exe文件.这个.exe文件究竟是什么?是不是用java编写的java编译器,那怎么会有执行它的.exe文件呢?
Java编译器(至少是Sun/Oracle JDK附带的编译器)确实是用Java编写的.javac.exe
它只是一个处理命令行参数的启动程序,其中一些参数传递给运行编译器的JVM,另一些传递给编译器本身.
如果编译的代码是java,那么编译器代码是如何在编译阶段执行的,因为它是jvm执行java代码的工作.语言本身如何编译自己的语言代码?这对我来说似乎都是鸡和蛋的问题.
许多(如果不是大多数)编译器都是用他们编译的语言编写的.显然,在某个早期阶段,编译器本身必须由其他东西编译,但在"bootstrapping"之后,任何新版本的编译器都可以由旧版本编译.
现在.class文件到底包含什么?它是文本形式的抽象语法树,是表格信息,它是什么?
Java虚拟机规范中描述了类文件格式的详细信息.
好吧,javac和jvm通常都是原生二进制文件.它们是用C语写的.用Java编写它们当然是可能的,只需要首先需要本机版本.这称为"引导捆绑".
有趣的事实:编译为本机代码的大多数编译器都是用他们自己的语言编写的.但是,它们都必须首先使用另一种语言编写本机版本(通常为C).相比之下,第一个C编译器是用汇编程序编写的.我认为第一个汇编程序是用机器代码编写的.(或者,使用蝴蝶 ;)
.class文件是javac生成的字节码.它们不是文本的,它们是类似于机器代码的二进制代码(但是,具有不同的指令集和架构).
jvm在运行时有两个选项:它可以解释字节代码(假装是CPU本身),也可以JIT(实时)将其编译为本机代码.当然,后者更快,但更复杂.
归档时间: |
|
查看次数: |
44174 次 |
最近记录: |