什么是编译
编译是利用编译程序从源语言编写的源程序产生目标程序的过程,一般是指把用高级程序设计语言书写的源程序,翻译成等价的机器语言格式目标程序的翻译程序的过程。完成编译过程的工具就是编译器。
编译过程
java中代码编译是由Javac编译器来完成;
Javac编译器将Java源文件(.java文件)编译成字节码文件(.class文件,是特殊的二进制文件,二进制字节码文件)
编译过程步骤如下 :
![](https://img.haomeiwen.com/i16011060/06a2fcbf555b7547.jpg)
具体每一步的作用就属于编译原理范畴了。
- 词法分析:读取源代码,一个字节一个字节的读进来,找出这些词法中我们定义的语言关键词如:if、else、while等,识别哪些if是合法的哪些是不合法的,结果是产生Token流。
- 语法分析:就是对词法分析中得到的token流进行语法分析,这一步就是检查这些关键词组合在一起是不是符合Java语言规范。如if的后面是不是紧跟着一个布尔型判断表达式,结果是产生抽象语法树。
- 语义分析:语法分析完成之后也就不存在语法问题了,语义分析的主要工作就是把一些难懂的,复杂的语法转化成更简单的语法。就如难懂的文言文转化为大家都懂的百话文,或者是注释一下一些不懂的成语。
- 字节码生成:将会根据经过注释的抽象语法树生成字节码,也就是将一个数据结构转化为另外一个数据结构。就像将所有的中文词语翻译成英文单词后按照英文语法组装文英文语句。代码生成器的结果就是生成符合java虚拟机规范的字节码。
javac命令
语法:
javac [ options ] [ sourcefiles ] [ @files ]
options
命令行选项。
sourcefiles
一个或多个要编译的源文件(比如 MyClass.java)。
@files
一个或多个对源文件进行列表的文件。
常用选项
- -classpath(-cp)指定你依赖的类的class文件的查找位置。在Linux中,用“:”分隔classpath,而在windows中,用“;”分隔。
编译时指定了classpath,在运行的时候注意也可能需要classpath指定依赖的class文件,比如
java -cp ../ttdir/:../classes Test
,依赖的class文件放在ttdir文件夹中,Test.class放在classes文件夹中(classpath中也要说明需要运行的类的位置)
- -sourcepath指定你依赖的类的java文件的查找位置。
- -d指定单独的类文件目标位置
javap命令
可以查看java编译器生成的字节码.class文件或者进行反汇编。
语法:
javap [ options ] [ file ]
例子
有一个类Test.java
public class Test {
int x=1;
static int z=3;
public static void main(String[] args) {
int y=2;
System.out.printf("Hello world \n"+z+y);
}
}
编译得到Test.class
执行:
$ javap -c Test.class
结果:
Compiled from "Test.java"
public class Test {
int x;
static int z;
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field x:I
9: return
public static void main(java.lang.String[]);
Code:
0: iconst_2
1: istore_1
2: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
5: new #4 // class java/lang/StringBuilder
8: dup
9: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
12: ldc #6 // String Hello world \n
14: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: getstatic #8 // Field z:I
20: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
23: iload_1
24: invokevirtual #9 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
27: invokevirtual #10 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
30: iconst_0
31: anewarray #11 // class java/lang/Object
34: invokevirtual #12 // Method java/io/PrintStream.printf:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/io/PrintStream;
37: pop
38: return
static {};
Code:
0: iconst_3
1: putstatic #8 // Field z:I
4: return
}
网友评论