在开始进入词法分析代码流程之前,先介绍一些重要的类:
它的定义最重要的字段如下:
public class Context {
/***Theunderlyingmapstoringthedata.*Wemaintaintheinvariantthatthistablecontainsonly*mappingsoftheform*{@literalKey->T}*or*{@literalKey->Factory}*/
protectedfinalMap,Object>ht=newHashMap<>();
/***Thetableofpreregisteredfactories.*/
privatefinalMap,Factory>>ft=newHashMap<>();
/**Thekeytable,providingauniqueKeyforeachClass.*/
privatefinalMap,Key>>kt=newHashMap<>();
}
这个类是编译器中最重要的类,它是所有类通信与相互引用的枢纽,同时也为大家扩展这个编译器实现简单的方式。
有三种使用方式:简单的模式,通过Context.put(Key, Factory fac)来注册一个对象创建工厂,在获取的时候直接Context.get(Key)来获取,一般这个对是第每一次调用产生一个新的对象。com.sun.tools.javac.api.JavacTaskPool$ReusableContext$ReusableJavaCompiler这个类就属于这种方式。
如果不是单例模式的类,则注册的时候通过put(XXXClass.class, Context.Factory的子类),获取通过XXXClass.instance(XXXClass.class)来获取。这样的类不多。
扩展子类模式:类对象通过XXXClass.preRegister来注册(例如com.sun.tools.javac.file.JavacFileManager.java通过XXXClass.instance(context)来获取。一般都是单例模式。
这个类是编译整个流程执行的类,执行流程代码在第896行的compile函数。分两个函数链:
第一链:这个阶段完成会产生一个todo的队列给下阶段使用。
// These method calls must be chained to avoid memory leaks
processAnnotations(
enterTrees(
stopIfError(CompileState.PARSE,
initModules(stopIfError(CompileState.PARSE, parseFiles(sourceFileObjects))))
),
classnames
);
第二链:
case BY_TODO:
while (!todo.isEmpty())
generate(desugar(flow(attribute(todo.remove()))));
break;
这个类及其子类,在intellij Windows平台中按Ctrl+H就能看到所有的子类,是抽象语法树(AST, Abstract Syntax Tree)的节点,表示代码的一个个单元。其中JCComplicationUnit表示一个java文件的结果,其它的从名字上就能看出是什么代码。代码词法分析的结果是一个List,有几个java文件就有几个JCComplicationUnit,如果有module-info.java也会自动编译上。
这个的子类代表一个具体的Java符号,比如ClassSymbol代码广泛的类类型,简称广类类型【我在这系列的文章都会用这个称呼,因为容易与类类型混淆。类类型表示class对象,广类类型表示类(class)、接口(interface)、枚举(enum),记录(record)】.
这个类及其子类是标识Symbol的具体Java类型的,比如基础类型(BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, BOOLEAN)还有ClassType, ArrayType, MethodType等。