java编译器源码解析-语义分析-填充符号表
一、生成符号表
填充符号表的核心逻辑在com.sun.tools.javac.comp.Enter类。
在讨论填充符号表的逻辑之前,首先要明确一下,什么是符号?
我们在java代码中,可能会声明一个类,类中有属性和方法,这些对于计算机而言,都是一种符号。
在java编译器的实现中,定义了专门的符号类Symbol及相关的子类
符号有名称,就是我们理解的类名、方法名和属性名。
除此之外,符号还有类型,java专门设计了一套符号类型系统来标识它。
我们举个例子
int a=0;
我们知道,a是一个变量,但编译器认为a是一个VarSymbol,它的类型是JCPrimitiveType.
在执行程序的时候,原生类型和引用类型有不同的处理方式。
原生类型可能存放在常量池中,但引用类型必须存在堆中,所以在编译器在编译期间就需要标识起来。
填充符号表分为两个阶段:
第一:类符号填充Enter
主方法为complete()所有类都进入其作用域,在visit类声明的时候,给相关的JCClassDecl节点的sym类型定义了一个ClassSymbol的值。
类符号填充完成后,进入第二阶段,调用enterMember.complete方法
第二:其他成员符号填充
逻辑在MemberEnter类的complete方法中
MemberEnter.visitMethodDef()给方法声明节点的符号表填充符号。
MemberEnter.visitVarDef()给变量声明节点的符号表填充符号。
第三:其他的符号填充在后续阶段完成
生成符号的同时,符号的作用域也被识别了出来。