概述
-
前端编译器:把.java文件转变成.class文件的过程
例如:JDK的Javac、Eclipse JDT中的增量式编译器(ECJ)
-
即时编译器(常称JIT编译器,Just In Time Compiler)运行期把字节码转变成本地机器码的过程。
例如:HotSpot虚拟机的C1、C2编译器,Graal编译器
-
提前编译器(常称AOT编译器,Ahead Of Time Compiler)直接把程序编译成与目标机器指令集相关的二进制代码的过程。
例如:JDK的Jaotc、GNU Compiler for the Java(GCJ)
Javac编译器
Javac本身就是一个由Java语言编写的程序
Javac的源码与调试
下载openJDK8的代码,JDK_SRC_HOME/langtools/src/share/classes/com/sun/*目录下的源文件全部复制到工程的源码目录中
从Javac代码的总体结构来看,编译过程大致可以分为1个准备过程和3个处理过程:
- 准备阶段:初始化插入式注解处理器
- 解析与填充符号表过程,包括:
- 词法、语法分析。将源代码的字符流转变为标记集合,构造出抽象语法树。
- 填充符号表。产生符号地址和符号信息。
- 插入式注解处理器的注解处理过程:插入式注解处理器的执行阶段,本章的实战部分会设计一 个插入式注解处理器来影响Javac的编译行为。
- 分析与字节码生成过程,包括:
- 标注检查。对语法的静态信息进行检查。
- 数据流及控制流分析。对程序动态运行过程进行检查。
- 解语法糖。将简化代码编写的语法糖还原为原有的形式。
- 字节码生成。将前面各个步骤所生成的信息转化成字节码。
上述3个处理过程里,执行插入式注解时又可能会产生新的符号,如果有新的符号产生,就必须转回到之前的解析、填充符号表的过程中重新处理这些新符号,从总体来看,三者之间的关系与交互顺 序如图10-4所示。
Javac编译动作的入口是 com.sun.tools.javac.main.JavaCompiler类,上述3个过程的代码逻辑集中在这个类的compile()和compile2() 方法里
解析与填充符号表
- 词法、语法分析
- 填充符号表
注解处理器
语义分析与字节码生成
- 标注检查
- 数据及控制流分析
- 解语法糖
- 字节码生成
Java语法糖的味道
泛型
泛型的本质是参数化类型(Parameterized Type)或者参数化多态(Parametric Polymorphism)的应用,即可以将操作的数据类型指定为方法签名中的一种特殊参数,这种参数类型能够用在类、接口和方法的创建中,分别构成泛型类、泛型接口和泛型方法。
- Java与C#的泛型
Java选择的泛型实现方式叫作“类型擦除式泛型”(Type Erasure Generics)
//Java中不支持的泛型用法
public class TypeErasureGenerics<E> {
public void doSomething(Object item) {
if (item instanceof E) { // 不合法,无法对泛型进行实例判断
...
}
E newItem = new E(); // 不合法,无法使用泛型创建对象
E[] itemArray = new E[10]; // 不合法,无法使用泛型创建数组
}
}
- 类型擦除
裸类型应被视为所有该类型泛型化实例的共同父类型(Super Type)
import java.util.ArrayList;
//裸类型赋值
public class Test {
public static void main(String[] args) {
ArrayList<Integer> ilist = new ArrayList<Integer>();
ArrayList<String> slist = new ArrayList<String>();
ArrayList list; // 裸类型
list = ilist;
list = slist;
}
}
//泛型擦除前的例子
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("hello", "你好");
map.put("how are you?", "吃了没?");
System.out.println(map.get("hello"));
System.out.println(map.get("how are you?"));
}
}
//泛型擦除后的例子
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map map = new HashMap();
map.put("hello", "你好");
map.put("how are you?", "吃了没?");
//加了类型强转
System.out.println((String) map.get("hello"));
System.out.println((String) map.get("how are you?"));
}
}
//原始类型的泛型(目前的Java不支持)
//不支持int、long与Object之间的强制转型
ArrayList<int> ilist = new ArrayList<int>();
ArrayList<long> llist = new ArrayList<long>();
ArrayList list;
list = ilist;
list = llist;
import java.util.List;
//当泛型遇见重载1
//这段代码是不能被编译的,因为参数List<Integer>和List<String>编译之后都被擦除了,变成了同一种的裸类型List,类型擦除导致这两个方法的特征签名变得一模一样
public class GenericTypes {
public static void method(List<String> list) {
System.out.println("invoke method(List<String> list)");
}
public static void method(List<Integer> list) {
System.out.println("invoke method(List<Integer> list)");
}
}
擦除法所谓的擦除,仅仅是对方法的Code属性中的字节码进行擦除,实际上元数据中还是保留了泛型信息,这也是我们在编码时能通过反射手段取得参数化类型的根本依据。
自动装箱、拆箱与遍历循环
import java.util.*;
//自动装箱、拆箱与遍历循环
public class Test {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
int sum = 0;
for (int i : list) {
sum += i;
}
System.out.println(sum);
}
}
//自动装箱、拆箱与遍历循环编译之后
/*代码中包含了泛型、自动装箱、自动拆箱、遍历循环与变长参数5种语法糖,泛型,自动装箱、拆箱在编译之后被转化成了对应的包装和还原方法,如本例中的Integer.valueOf()与Integer.intValue()方法,而遍历循环则是把代码还原成了迭代器的实现,这也是为何遍历循环需要被遍历的类实现Iterable接口的原因。最后再看看变长参数,它在调用的时候变成了一个数组类型的参数*/
public class Test {
public static void main(String[] args) {
List list = Arrays.asList(new Integer[]{
Integer.valueOf(1),
Integer.valueOf(2),
Integer.valueOf(3),
Integer.valueOf(4)});
int sum = 0;
for (Iterator localIterator = list.iterator(); localIterator.hasNext(); ) {
int i = ((Integer) localIterator.next()).intValue();
sum += i;
}
System.out.println(sum);
}
}
条件编译
//Java语言的条件编译
public class Test {
public static void main(String[] args) {
if (true) {
System.out.println("block 1");
} else {
System.out.println("block 2");
}
}
}
//Class文件的反编译结果:
public class Test {
public static void main(String[] args) {
System.out.println("block 1");
}
}
源自书籍:深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)-周志明
网友评论