分析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的更多相关文章

  1. memcached源码分析-----item过期失效处理以及LRU爬虫

    memcached源码分析-----item过期失效处理以及LRU爬虫,memcached-----item 转载请注明出处:http://blog.csdn.net/luotuo44/article ...

  2. effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  3. 读书笔记 effective c++ Item 48 了解模板元编程

    1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在 ...

  4. 【NLP】十分钟快览自然语言处理学习总结

    十分钟学习自然语言处理概述 作者:白宁超 2016年9月23日00:24:12 摘要:近来自然语言处理行业发展朝气蓬勃,市场应用广泛.笔者学习以来写了不少文章,文章深度层次不一,今天因为某种需要,将文 ...

  5. zabbix系列之七——安装后配置二Userparameters

    1User parameters(用户自定义参数) 1.1配置 描述 详细 备注 简介 1执行zabbix中未预定义的agent check时使用 配置 1)    zabbix agent的配置文件 ...

  6. 一分钟搞定触手app主页酷炫滑动切换效果

    代码地址如下:http://www.demodashi.com/demo/12826.html 前言: 前几天在看手机直播的时候,自己就用上了触手app.一进到主页就看上了里面页面切换的效果,自己想这 ...

  7. OO第一单元总结——求导

    一.基于度量分析程序结构 (一)第一次作业 (1)设计思路 本次作业只涉及到简单幂函数通过加减运算而复合而成的函数,因此笔者自然的把函数分成了函数本体以及单个的项两个部分,在笔者的设计中两个类的功能如 ...

  8. Android ListView实现不同item的方法和原理分析

    ListView实现不同item的方法和原理分析 一问题抛出Listview是android里面的重要组件,用来显示一个竖向列表,这个没有什么问题:但是有个时候列表里面的item不是一样的,如下图,列 ...

  9. Android开发学习之路-RecyclerView的Item自定义动画及DefaultItemAnimator源码分析

    这是关于RecyclerView的第二篇,说的是如何自定义Item动画,但是请注意,本文不包含动画的具体实现方法,只是告诉大家如何去自定义动画,如何去参考源代码. 我们知道,RecyclerView默 ...

随机推荐

  1. Ajax传数据到servlet

    //jsp代码 <%@ page language="java" contentType="text/html; charset=ISO-8859-1" ...

  2. sudo执行脚本找不到环境变量和命令

    简介 变量 普通用户下,设置并export一个变量,然后利用sudo执行echo命令,能得到变量的值,但是如果把echo命令写入脚本,然后再sudo执行脚本,就找不到变量,未能获取到值,如题情况如下: ...

  3. Codeforces791A Bear and Big Brother

    A. Bear and Big Brother time limit per test 1 second memory limit per test 256 megabytes input stand ...

  4. QT5.4.0安装以及与VS2010整合安装---64bit操作系统解决方案

    QT5.4.0安装以及与VS2010整合安装---64bit操作系统解决方案 注意,目前QT官网不能下载,必须提供注册,然后才可以下载. 网上不同版本安装的细节有差异,特将我的安装相关操作贴出来,希望 ...

  5. 数字签名、数字证书的原理以及证书的获得java版

    数字签名原理简介(附数字证书) 首先要了解什么叫对称加密和非对称加密,消息摘要这些知识. 1. 非对称加密 在通信双方,如果使用非对称加密,一般遵从这样的原则:公钥加密,私钥解密.同时,一般一个密钥加 ...

  6. MySQL表名大小写设置

    1 简介    在MySQL中,数据库对应数据目录中的目录.数据库中的每个表至少对应数据库目录中的一个文件(也可能是多个,取决于存储引擎).因此,所使用操作系统的大小写敏感性决定了数据库名和表名的大小 ...

  7. Android-AndroidStudio加载工程方式-gradle文件夹

    例如:在其他地方,其他工作人员哪里的OpenGateDemo工程是OK的, 然后Copy到李四的电脑上运行是报错,其实所有的错误都和gradle有关: 第一步,李四电脑运行OpenGateDemo工程 ...

  8. C#如何在List里求某一列的數值的和SUM

    var X=Xlist.Sum(key => key.XXX);

  9. GeneralizedLinearAlgorithm in Spark MLLib

    GeneralizedLinearAlgorithm SparkMllib涉及到的算法 Classification Linear Support Vector Machines (SVMs) Log ...

  10. Docker 持续集成初次体验

    背景 在家的时候,实在不想做其他的,想起之前参加的一场关于docker的座谈会,于是想搞以下docker. 开始 在道客云上搞了一下持续集成,总体来说,比较好用的. 写了一个Go程序,就是之前写的发邮 ...