Javac之Environment
关于Env的源代码如下:
/** A class for environments, instances of which are passed as
* arguments to tree visitors. Environments refer to important ancestors
* of the subtree that's currently visited, such as the enclosing method,
* the enclosing class, or the enclosing toplevel node. They also contain
* a generic component, represented as a type parameter, to carry further
* information specific to individual passes.
*
* 一个类的环境,它的实例将被作为树访问者的参数进行传递。环境涉及到重要的子树的先祖,
* 子树是目前被访问过的。例如封闭的方法、封闭的类或者是封闭的顶层结点。它们也包含了
* 一个一般性的组件,被描述为类型参数,针对个别的传递携带更多的信息
*
*/
public class Env<A> implements Iterable<Env<A>> {
/** The next enclosing env.
*
* 下一个封闭的环境,和作用域是不同的。这个与语法树的组织嵌套是一样的
*/
public Env<A> next;
/** The env enclosing the current class.
*
* 参考文章:
*/
public Env<A> outer;
/** The tree with which this environment is associated.
*/
public JCTree tree;
/**
* The enclosing toplevel tree.封闭的顶层语法树,语法节点类型为JCCompilationUnit
*/
public JCCompilationUnit toplevel;
/** The next enclosing class definition.
*/
public JCClassDecl enclClass;
/** The next enclosing method definition.
*/
public JCMethodDecl enclMethod;
/** A generic field for further information.
*/
public A info;
// ...
}
主要通过三种途径来获取Env对象,如下:
(1)构造函数创建Env对象并返回
代码如下:
/** Create an outermost environment for a given (toplevel)tree,with a given info field.
*/
public Env(JCTree tree, A info) {
this.next = null;
this.outer = null;
this.tree = tree; // 初始化时就赋值
this.toplevel = null;
this.enclClass = null;
this.enclMethod = null;
this.info = info; // 初始化时就赋值
}
调用的地方如下图所示。

除去Env中的dup方法与子类通过super()进行调用后,剩下了两个主要的地方在调用。
(2)调用dupto()方法获取Env对象
/** Duplicate this environment into a given Environment,
* using its tree and info, and copying all other fields.
*/
public Env<A> dupto(Env<A> that) {
that.next = this;
that.outer = this.outer;
that.toplevel = this.toplevel;
that.enclClass = this.enclClass;
that.enclMethod = this.enclMethod;
return that;
}
被调用的地方如下图所示。
(3)调用dup()方法获取Env对象
/** Duplicate this environment, updating with given tree,
* and copying all other fields.
*/
public Env<A> dup(JCTree tree) { // 更新tree的信息
return dup(tree, this.info);
}
/** Duplicate this environment, updating with given tree and info,
* and copying all other fields.
*/
public Env<A> dup(JCTree tree, A info) { // 更新tree与info的信息
return dupto(new Env<A>(tree, info));
}
如上两个dup()方法都将调用dupto()方法来获取Env对象。
第一个方法的调用地方如下图所示。

第二个方法的调用地方如下图所示。

下面来介绍各个属性。
1、info属性:
参考文章:https://www.cnblogs.com/extjs4/p/9285113.html
2、outer属性:
class A {
static class B { // 只有在toplevel类中可用static,所有的内部类不可以使用static关键字
int b = 2;
public void methodB(){
class C {
Object c = new Object(){
int c = b;
};
{
class D{
public void t() {
int c = b;
}
}
}
}
}
}
}
对于匿名内部类的int c = b语句来说,其outer是JCNewClass(JCNewClass属于类C)。类C的outer为类B的JCBlock。类B的outer为类A。
对于方法t中的int c = b语句来说,语句属于类D,类D的外层为JCBlock(JCBlock{classD{...}},而JCBlock(JCBlock{classD{...}}的outer为methodB的Block。
3、enclClass属性:
一个编译单元JCCompilationUnit的Env下的enclClass属性为:
/** Create a fresh environment for toplevels.
* @param tree The toplevel tree.
*/
public Env<AttrContext> topLevelEnv(JCCompilationUnit tree) {
// 初始化namedImportScope属性
tree.namedImportScope = new ImportScope(tree.packge);
tree.starImportScope = new StarImportScope(tree.packge);
Env<AttrContext> localEnv = new Env<AttrContext>(tree, new AttrContext());
localEnv.toplevel = tree;
// predefClassDef:A dummy class to serve as enclosingClass
// for toplevel environments.
localEnv.enclClass = predefClassDef;
// JCCompilationUnit的环境Scope中使用的是namedImportScope
localEnv.info.scope = tree.namedImportScope;
localEnv.info.lint = lint;
return localEnv;
}
是一个预先定义好的predefClassDef。
public Env<AttrContext> classEnv(JCClassDecl tree, Env<AttrContext> env) {
Scope sp = new Scope(tree.sym);
AttrContext ac = env.info.dup(sp);
Env<AttrContext> localEnv = env.dup(tree, ac);
localEnv.enclClass = tree;
localEnv.outer = env;
localEnv.info.isSelfCall = false;
localEnv.info.lint = null; // leave this to be filled in by Attr,
// when annotations have been processed
return localEnv;
}
被调用的截图如下:

JCClassDecl语法节点的Env的属性enclClass为自己本身,而JCTypeParameter语法节点举例如下:
interface IA{}
interface IB{}
class CA{}
class CB{}
class TestC<T extends CA&IA&IB>{
public <B extends CB&IA&IB> void method(B b){}
}
则visitTypeParameter()方法的cd属性类型为JCClassDecl,分别为:
1、public abstract class T extends CA implements IA,IB{} 最终生成的Env如下截图。

2、public abstract class B extends CB implements IA,IB{} 最终生成的Environment如下截图。

对于Scope属性举个例子,如下:
package com.test07;
import java.io.FileInputStream;
import java.io.InputStream;
class TestScope {
public int a = 2;
public void test(int b) {
int c = 3;
for (int d = 3; a < 6; a++) {
int e = 4;
}
}
}
Scope如下截图。

在如上的例子中,JCVariableDecl节点及子结点的staticLevel都为1,而其父结节点及以上为0。再举个例子,如下:
public class Test3{
static{ // staticLevel = 1
// 在static块中不允许再有static出现,如
// static int a = 1;
// static class A{}
// class A{
// public static void m1(){}
// }
int a = 1; // staticLevel = 1
}
// 这个类的staticLevel为0,与一般类没有任何区别
static class Inner{ // staticLevel = 0
public static void m1(){ // staticLevel = 1
int b = 1; // staticLevel = 1
}
}
}
举个例子,如下:
interface I{
void m1();
}
public class Test3{
static void t(){}
static I a = new I(){
@Override
public void m1() {
t();
}
};
}
那么t()的环境Env的结构如下截图。
这是outer属性,而next属性和语法树的组织结构是严格一致的,如下截图。

Javac之Environment的更多相关文章
- Fedora javac 命令提示 [javac: 未找到命令...]
[joy@localhost ~]$ java -version openjdk version "1.8.0_91" OpenJDK Runtime Environment (b ...
- Java SE series:1. environment configure and Hello world! [We use compiler and packager to create an application!]
1. cli (command line interface) and gui (graphic user interface) use javahome path, search classpath ...
- Storm(1) - Setting Up Development Environment
Setting up your development environment 1. download j2se 6 SDK from http://www.oracle.com/technetwor ...
- JDK Environment Variable And Change default JDK
Environment Variable : change(import) /etc/bashrc export JAVA_HOME=/software/jdk1.8.0 export PATH=$J ...
- Config the Android 5.0 Build Environment
In this document Choosing a Branch Setting up a Linux build environment Installing the JDK ...
- 在XP系统下搭建maven环境出的问题 Unable to locate the Javac Compiler in: C:\Program Files\Java\jre6\..\lib\tools.jar
Build errors for spider; org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute g ...
- google官方提供的编译android源码的环境初始化,Initializing a Build Environment
原文网址:http://source.android.com/source/initializing.html Initializing a Build Environment IN THIS DOC ...
- 解决linux下javac -version和java -version版本显示不一致
解决linux下javac -version和java -version版本显示不一致 [javascript] view plaincopy [root@localhost usr]# $JAVA_ ...
- 第六章-Javac符号表
需要参考: (1)Architecture of a Java Compiler (2)关于符号Symbol第一篇 (3)关于符号Symbol第二篇 (4)关于类型Type (5)关于作用域范围Sco ...
随机推荐
- 深入解析String#intern
转自:https://tech.meituan.com/in_depth_understanding_string_intern.html 深入解析String#intern john_yang ·2 ...
- sun.misc.BASE64Decoder的风险
问题描述 最近需要使用Base64上传图片,但是返现sun.misc.BASE64Decoder 为已经过期的包,此包为以前sun公司的内部包,可以下载此包,但是不利于现在Maven方式构建,可能会在 ...
- After Upgrade To Release 12.1.3 Users Receive "Function Not Available To This Responsibility" Error While Selecting Sub Menus Under Diagnostics (Doc ID 1200743.1)
APPLIES TO: Oracle Application Object Library - Version 12.1.3 to 12.1.3 [Release 12.1] Information ...
- Android工具类整合
Android-JSONUtil工具类 常用的Json工具类,包含Json转换成实体.实体转json字符串.list集合转换成json.数组转换成json public class JSONUtil ...
- struts2设置index.action为主页(另:web.xml编辑卡死问题解决)
本来是弄拦截器的问题,结果弄主页的时候,还是发现了问题. 公司网站的项目里面,是用index.action作为主页的,访问WEB-INF里面的html文件.可是我设置的却不成功,追根到底,一个原因,s ...
- QPS的计算
QPS = req/sec = 请求数/秒 Q:如何根据日志查看一个服务的qps A: 一般access.log是记录请求的日志,tail -f XXX.access.log ,可发现格式如下: 前 ...
- 1、ASP.NET Core2.0之Model、View、Controller
一.新建空项目 打开VS2017,新建→项目,选择如下: 点击,确定,弹出的界面选择如下: 选择空项目,因为选择其他的话会自动生成很多用不到的类,显得项目不够“清爽”,ASP.NET Core选择2. ...
- “全栈2019”Java第九十九章:局部内部类与继承详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 【FAQ】tomcat启动jdk版本不一致
一.tomcat7.exe与startup.bat的区别: 1.这两个都可以启动tomcat,但tomcat7.exe必须安装了服务才能启动,而startup.bat不需要 2.另外一个区别是它们启动 ...
- byte转文件流 下载到本地
此方法将byte类型文件转为文件流保存到本地 byte 经过BASE64Decoder 进行编码之后的类型 所以需要解码 防止出现乱码及文件损毁 /** * byte 转文件 下载到本地 * @par ...