前言
基础知识也要懂一些,也可以帮助解决平常遇到的问题。
编译:Java代码转化为字节码class
低级语言是计算机认识的语言、高级语言是程序员认识的语言。那么如何从高级语言转换成低级语言呢?这个过程其实就是编译。从java源码到class文件是为了后面可以加载到jvm中,这个过程称为编译过程,这个过程由编译器来执行,使用javac命令执行得到class文件:
javac HelloWorld.java
一张图来看看编译到底做了什么:
拆解一下过程,我们来分析分析:
-
词法分析
将java源代码的字符流转变为标记(Token)的集合,Token是编译过程中的最小元素,即识别每一个单词是什么东,关键字、变量名、字面量、运算符都可以成为标记。如int a = b + 2 这句代码包含了6个标记,分别是int 、 a、=、b、+、2。 -
语法分析
根据词法分析得到的Token序列构造一颗抽象语法二叉树。包、类型、修饰符、运算符、接口、返回信息、代码注释等都是语法结构,如果不符合会报错。 -
语义分析
语法树能够表示一个结构正确的源程序的抽象,但无法保证源程序是符合逻辑的,语义分析的主要任务就是对结构上正确的源程序进行上下文有关的性质审查。语义分析是会做类型检查,控制流检查,类型检查等等,比如类语法糖是在计算机语言中添加某种语法,用来提高程序的可读性,减少代码的出错机会,会在这个环节进行解析。如泛型、变长参数、自动拆箱和装箱等。 -
注解过程
JDK1.5加入了对注解的支持,需要在编译期间对注解进行处理。我们可以将注解处理器看作一组插件,可以修改抽象语法树中的任意元素。在处理注解的过程中,每次修改抽象语法树后,编译器将回到解析及填充符号表的过程重新处理。 -
字节码生成
里面都是16进制的内容,看不懂,需要借助工具来看,字节码生成阶段不仅仅把前面各个步骤生成的信息(语法树、符号表)转化为字节码写到磁盘中,编写器还进行了少量的代码添加和转换工作。编译后的字节码文件格式主要分为两部分:常量池和方法字节码。常量池记录的是代码出现过的所有token(类名,成员变量名等等)以及符号引用(方法引用,成员变量引用等等);方法字节码放的是类中各个方法的字节码。
举例分析
我们来看一个代码被编译后的情况:
//MainApp.java
public class MainApp {
public static void main(String[] args) {
Animal animal = new Animal("Puppy");
animal.printName();
}
}
//Animal.java
public class Animal {
public String name;
public Animal(String name) {
this.name = name;
}
public void printName() {
System.out.println("Animal ["+name+"]");
}
}
常量池内容:
方法字节码: