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()给变量声明节点的符号表填充符号。

第三:其他的符号填充在后续阶段完成

生成符号的同时,符号的作用域也被识别了出来。