分析Item
分析Item例子1:
class Parent {
/*
<init>() {
super(); // JCES树节点,Item(void)
px = 0; // JCES树节点,AssignItem(lhs = MemberItem(px))
}
*/
int px = 0;
}
public class Test07 extends Parent {
/*
public <init>() {
super(); // JCES树节点,Item(void)
px = 1; // JCES树节点,AssignItem(lhs = MemberItem(px))
}
*/
int px = 1;
public void t() {
String[] a = new String[10];
a[0] = "str"; // JCES树节点,AssignItem(lhs = IndexedItem(object))
String b = a[0];
int subx = this.px;
int superx = super.px;
if (b == "str") {
instanceMethod(); // JCES树节点,Item(void)
} else {
staticMethod(); // JCES树节点,StackItem(int)
}
// JCES树节点,item=AssignItem(lhs = MemberItem(px))
px++;
new String(); // JCES树节点,StackItem(object)
// (Object)new String(); // 这样的书写形式不被允许
}
public void instanceMethod() {}
public static int staticMethod() {
return 0;
}
}
在访问Gen类的visitExec(JCExpressionStatement tree) 方法时,首先知道哪些表达式可能是ExpressionStatement,如下上下文无关方法:
ExpressionStatement:
StatementExpression ;
StatementExpression:
Assignment
PreIncrementExpression
PreDecrementExpression
PostIncrementExpression
PostDecrementExpression
MethodInvocation
ClassInstanceCreationExpression
对于StackItem来说,调用drop()后为空实现,不需要将方法的返回值压入栈,也不需要存储到本地变量表。对于AssignItem的drop()方法的实现如下:
public void drop() {
lhs.store();
}
来说要看lhs,而lhs可能是如下几种情况:
AssignmentExpression:
ConditionalExpression
Assignment
Assignment:
LeftHandSide AssignmentOperator AssignmentExpression
LeftHandSide:
ExpressionName
FieldAccess
ArrayAccess
AssignmentOperator: one of
= *= /= %= += -= <<= >>= >>>= &= ^= |=
所以只可能是IndexedItem、MemberItem与LocalItem、StaticItem这几项,调用其 store()方法:
(1)IndexedItem项的store()方法实现如下:
public void store() {
items.code.emitop0(iastore + typecode);
}
(2)MemberItem项的store()方法实现如下。
public void store() {
int poolIndex = items.pool.put(member);
items.code.emitop2(putfield, poolIndex);
}
MemberItem代表实例成员或者实例方法,在这里不可能为实例方法。因为方法返回的类型是VAL而并非VAR。
(3)LocalItem项的store()方法实现如下。
如在方法中声明如下
int b; b = 3;

其LocalItem的store()方法的实现如下:
public void store() {
if (reg <= 3) {
int opcode = istore_0 + Code.truncate(typecode) * 4 + reg;
items.code.emitop0(opcode);
}else {
int opcode = istore + Code.truncate(typecode);
items.code.emitop1w(opcode, reg);
}
// 往本地变量表中存储局部变量,关于store指令的压入只在这里有,其它地方没有
// 这个在本地变量表中存储的变量通过store拿到了赋值,所以生命周期开始了
items.code.setDefined(reg);
}
(4)StaticItem项的store()方法实现如下。
public void store() {
int i = items.pool.put(member);
items.code.emitop2(putstatic, i);
}
对如下的例子进行分析,例子如下:
class Parent{
int px = 0;
}
public class Test08 extends Parent{
int px = 1;
public void t(){
String[] a = new String[10];
a[0] = "str";
String b = a[0];
int subx = this.px;
int superx = super.px;
if(b=="str"){
instanceMethod();
}else{
staticMethod();
}
}
public void instanceMethod(){}
public static void staticMethod(){}
}
1、super()语句
调用链为visitExec(JCExpressionStatement tree)->visitIdentifier(JCIdentifier tree),其中tree的参数如下截图。

生成SelfItem后调用load()方法,压入指令aload_0,返回StackItem(object)后放弃,在stack中压入的类型为UninitializedType类型。
生成MemberItem(Parent() nonvirtual)后做为result结果,从visitIdentifier()方法中返回。为的是调用父类的构造函数,这个MemberItem如下截图。

调用MemberItem的invoke()方法,常量池中放入父类构造函数,生成invokespecial调用指令。
返回Item(void),是因为调用方法后返回的就是void类型,调用这个类型的drop()方法,这个方法无任何操作。
2、px=1语句
调用visitIdentifier(JCIdentifier tree)方法,处理px关键字,其参数如下截图所示。

生成SelfItem(this)并调用其load()方法,压入指令aload_0。返回StackItem(object)。
生成MemberItem,这是由于px是个实例变量。
生成ImmediateItem(1)并调用其load()方法,压入指令iconst_1,返回StackItem(int)。
生成AssignItem,各参数值如下截图。

调用AssignItem的drop()方法,这个方法会调用MemberItem的store()方法,将px变量加入常量池后,压入指令putfield。
最后生成的字节码如下:
public com.test19.Test08();
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method com/test19/Parent."<init>":()V
4: aload_0
5: iconst_1
6: putfield #2 // Field px:I
9: return
3、String[] a = new String[10]语句
生成ImmediateItem(10)后调用load()方法,压入bipush指令,返回StackItem(int),舍弃。
将类型String放到常量池中,压入anewarray指令,生成StackItem(object),调用load()方法,由于本来是栈内的内容,所以方法调用后无任何改变。
生成LocalItem,各参数的值如下截图。

调用store()方法,压入astore_1指令。最终的字节码如下:
0: bipush 10 2: anewarray #3 // class java/lang/String 5: astore_1
4、a[0] = "str"语句
语法树结构如下截图。

生成localItem(type=java.lang.String[]; reg=1),调用load()方法将aload_1指令压入栈。返回stack(object),舍弃。
生成immediate(0),调用load()方法,压入iconst_0指令,返回stack(int),舍弃。
生成indexed(object),如下截图所示。

生成immediate(str),调用load()方法,压入ldc1指令,返回stack(object),舍弃。
生成assign(lhs = indexed(object)),如下截图所示。

调用drop()方法,这个方法会调用MemberItem的store()方法,压入指令aastore。
最终生成的class文件内容如下:
6: aload_1 7: iconst_0 8: ldc #4 // String str 10: aastore
5、String b = a[0]语句
生成localItem(type=java.lang.String[]; reg=1),调用load()方法,压入指令aload_1,返回StackItem(object),舍弃。
生成immediate(0),调用load()方法,压入iconst_0指令,返回StackItem(int),舍弃。
生成indexed(object),调用load()方法,压入aaload指令,返回StackItem(object),舍弃。
生成localItem(type=java.lang.String; reg=2),调用store()方法,压入astore_2指令。
最终生成的class内容如下:
11: aload_1 12: iconst_0 13: aaload 14: astore_2
6、int subx = this.px
生成SelfItem(this),调用load()方法,压入aload_0指令,生成StackItem(object),舍弃。
生成member(px),调用load()方法,将px放入常量池,压入指令getfield,生成StackItem(int),舍弃。
生成localItem(type=int; reg=3),调用store()方法,压入指令istore_3。
最终生成的class内容如下:
15: aload_0 16: getfield #2 // Field px:I 19: istore_3
7、if(b=="str"){instanceMethod();}else{staticMethod();}
生成的class文件内容如下:
26: aload_2 27: ldc #4 // String str 29: if_acmpne 39 32: aload_0 33: invokevirtual #6 // Method instanceMethod:()V 36: goto 42 39: invokestatic #7 // Method staticMethod:()V
7.1、b=="str"
生成localItem(type=java.lang.String; reg=2),调用load()方法后,压入aload_2指令,返回StackItem(object),舍弃。
生成immediate(str),调用load()方法,压入ldc1指令,返回StackItem(object),舍弃。
生成cond(if_acmpeq),调用mkCond()方法,无任何操作。
调用jumpFalse()方法,
7.2、instanceMethod()语句
生成SelfItem(this),调用load()方法,压入aload_0指令,返回StackItem(object),舍弃。
生成member(instanceMethod()), 调用invoke()方法,将instanceMethod()方法存储到常量池中,压入invokevirtual指令。生成Item(void),调用drop()方法,无任何操作。
压入goto_指令
7.3、staticMethod()语句
生成static(staticMethod()), 调用invoke()方法,将staticMethod()方法存储到常量池中,压入invokestatic指令。在压入指令的过程中会处理pendingJumps
生成Item(void),调用drop()方法,无任何操作。
压入goto_指令
8、方法返回
压入return_指令之前要解决thenExit
分析Item的更多相关文章
- memcached源码分析-----item过期失效处理以及LRU爬虫
memcached源码分析-----item过期失效处理以及LRU爬虫,memcached-----item 转载请注明出处:http://blog.csdn.net/luotuo44/article ...
- effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- 读书笔记 effective c++ Item 48 了解模板元编程
1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...
- 【NLP】十分钟快览自然语言处理学习总结
十分钟学习自然语言处理概述 作者:白宁超 2016年9月23日00:24:12 摘要:近来自然语言处理行业发展朝气蓬勃,市场应用广泛.笔者学习以来写了不少文章,文章深度层次不一,今天因为某种需要,将文 ...
- zabbix系列之七——安装后配置二Userparameters
1User parameters(用户自定义参数) 1.1配置 描述 详细 备注 简介 1执行zabbix中未预定义的agent check时使用 配置 1) zabbix agent的配置文件 ...
- 一分钟搞定触手app主页酷炫滑动切换效果
代码地址如下:http://www.demodashi.com/demo/12826.html 前言: 前几天在看手机直播的时候,自己就用上了触手app.一进到主页就看上了里面页面切换的效果,自己想这 ...
- OO第一单元总结——求导
一.基于度量分析程序结构 (一)第一次作业 (1)设计思路 本次作业只涉及到简单幂函数通过加减运算而复合而成的函数,因此笔者自然的把函数分成了函数本体以及单个的项两个部分,在笔者的设计中两个类的功能如 ...
- Android ListView实现不同item的方法和原理分析
ListView实现不同item的方法和原理分析 一问题抛出Listview是android里面的重要组件,用来显示一个竖向列表,这个没有什么问题:但是有个时候列表里面的item不是一样的,如下图,列 ...
- Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析
这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...
随机推荐
- 关于写css文件需要注意的事项
通常在项目中,我们尽量不要把style样式写在html中,而是使用外部.css文件的形式添加样式.在编写.css文件时,一定一定一定要注意,不要在一个css语句中写同级class名字,否则会出错,找不 ...
- js点击空白处触发事件
我们经常会出现点击空白处关闭弹出框或触发事件 <div class="aa" style="width: 200px;height: 200px;backgroun ...
- Codeforces Round#415 Div.2
A. Straight «A» 题面 Noora is a student of one famous high school. It's her final year in school - she ...
- Ueditor Word图片转存交互
三.Word图片转存交互 1.图片转存原理 所谓word图片转存,是指UEditor为了解决用户从word中复制了一篇图文混排的文章粘贴到编辑器之后,word文章中的图片数据无法显示在编辑器中,也无法 ...
- Redis集群master选举时长测试
在一台物理机上启动6个Redis实例,组成3主3从集群,端口号依次为:1379 ~ 1384,端口号1379.1380和1384三个为master,端口1379的进程ID为17620.现将进程1762 ...
- 【repost】对JAVASCRIPT匿名函数的理解(透彻版)
Query片段: view plaincopy to clipboardprint? (function(){ //这里忽略jQuery所有实现 })(); 半年前初次接触jQuery的时候,我也像其 ...
- Alpha阶段敏捷冲刺(四)
1.站立式会议 提供当天站立式会议照片一张 2.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中: 昨天已完成的工作. 祁泽文:实现了统计的基本按钮和界面. 徐璐琳:找到&q ...
- java基础-day15
第01天 java面向对象 今日内容介绍 u 包和权限修饰符 u 内部类 第1章 包和权限修饰符 1.1 包的概述 java的包,其实就是我们电脑系统中的文件夹,包里存放的是类文件. 当 ...
- Yarn的资源隔离机制
源调度和资源隔离是YARN作为一个资源管理系统,最重要和最基础的两个功能.资源调度由ResourceManager完成,而资源隔离由各个NodeManager实现,在文章“Hadoop YARN中内存 ...
- AngularJS 路由 resolve属性
当路由切换的时候,被路由的页面中的元素(标签)就会立马显示出来,同时,数据会被准备好并呈现出来.但是注意,数据和元素并不是同步的,在没有任何设置的情况下,AngularJS默认先呈现出元素,而后再呈现 ...