java代码是在线程中被执行的。每个线程都有它自己的执行栈,这个栈由很多帧组成。每个帧代表了一个方法调用:每当一个方法被调用时,就会创建一个新的帧,然后将这个帧放到当前线程的执行栈的栈顶。当这个方法正常返回时,或者发生了异常,这个帧就会从执行栈顶弹出,然后虚拟机会接着执行下一个位于执行栈栈顶的帧。
每个帧都包含两部分:一个局部变量区和一个操作数栈区。局部变量区包含了方法中定义的局部变量,可以通过索引值来随即访问。操作数栈区,如它的名字暗示,它是一个包含操作数的栈,这些数据被字节码指令所使用。这意味着这个栈中的数据只能以后进先出的顺序访问。
局部变量区和操作数栈的大小是由方法中的代码决定的。它们的大小是在编译时计算的,然后随着字节码指令一起存储在编译后的类中。
当帧被创建的时候,操作数栈初始化为空,局部变量包含当前对象的引用this(非静态方法)以及方法的参数。
局部变量区和操作数栈区的每一个插槽(图3.1中的方框)都能存储java中的任何值,除了long型和double型的值。因为long和double值需要2个插槽。
字节码指令可以划分为两类:1将局部变量的值传递到操作数栈的一小部分指令集,另外一部分指令2在操作数栈上进行操作:它们取得栈顶上的一些数据,进行计算,获得结果,然后将结果放回栈顶。
常见的指令1:
ILOAD,LLOAD,FLOAD,DLOAD和ALOAD指令读取一个局部变量的值,然后将它放置到操作数栈,这些指令的参数就是需要读取的局部变量的索引值i。
ISTORE,LSTORE,FSTORE,DSTORE和ASTORE指令是用来从操作数栈取得相应的数据然后保存会局部变量,它们的参数也是索引值i。
示例:
packagepkg;public classBean {private intf;public intgetF() {return this.f;
}public void setF(intf) {this.f =f;
}
}
其中getter方法的字节码为:
ALOAD 0
GETFIELD pkg/Bean f I
IRETURN
第一条指令读取索引位置为0的局部变量this,这个局部变量是在这个方法调用时创建的帧的过程中被初始化的,然后将这个局部变量放置到操作数栈栈顶。第二条指令从栈顶弹出这个值,this,然后将字段f的值放置到栈顶,this.f。最后一条指令从栈顶弹出得到的字段f的值,将它返回给调用者。这个方法执行过程中帧的状态如图
Setter方法的字节码如下:
ALOAD 0
ILOAD 1
PUTFIELD pkg/Bean f I
RETURN
第一条指令将this放置到操作数栈栈顶。第二条指令将索引为1的局部变量值放置到栈顶,这个索引的值为方法的参数,在方法调用创建帧的过程中初始化的。第三个指令从栈顶弹出这两个值,并将int值存贮到this对象的字段f中,this.f。最后一条指令,在源代码中是隐
式定义的,但是在编译后的代码中是必须的,它负责销毁执行帧并将调用返回给调用者。这个方法的执行帧的状态如图:
再看一个实际工作代码中某个类的一个方法
java代码如下:
/*** 并行计算各Handler
*@paramservices
*@paramdescriberMap
*@paramitems
*@paramsnapshots
*@paramareaId
*@paramoption
*@paramcontext
*@paramfees
*@paramdemoteLines*/
private void asynHandle(List services, Map describerMap, List items, Mapsnapshots,long areaId, DeliveryQueryOption option, MojoContext context, List fees, ListdemoteLines) {
Mailbox exitmb = new Mailbox();
FlowTask resTask= newFlowTask();for(Long service : services) {if(DeliveryConstant.ignoreServices.contains(service)) {continue;
}
PostageDescriberDO describer=describerMap.get(service);if (describer != null && describer.getType().intValue() !=DeliveryConstant.DELIVERY_TYPE_ADV) {
MojoEvent event= newMojoEvent(items, snapshots, service, areaId, option, context);
FlowTask preTask= newHandlerCalTask(event, fees, demoteLines);
Long dependencyType=DeliveryConstant.serviceMapping.get(service);
Mailbox exitFlag = new Mailbox();if(dependencyType != null &&services.contains(dependencyType)) {
MojoEvent mojoEvent= newMojoEvent(items, snapshots, dependencyType, areaId, option, context);
FlowTask task= newHandlerCalTask(mojoEvent, fees, demoteLines);
Mailbox exitMsg = new Mailbox();
preTask.informOnExit(exitMsg);//开启执行前置任务
preTask.start();//添加子任务
resTask.addSubFlowTask(task);
task.informOnExit(exitFlag);//preTask设置为task的前置任务,通过exitMsg识别
task.addPreTaskExtMsg(exitMsg);
}else{//添加子任务
resTask.addSubFlowTask(preTask);
preTask.informOnExit(exitFlag);
}//添加子任务完成标记
resTask.addSubTaskExtMsg(exitFlag);
}
}
resTask.start();
resTask.informOnExit(exitmb);
exitmb.getb(2000);//超时时间
}
该方法的字节码为:
private asynHandle(Ljava/util/List;Ljava/util/Map;Ljava/util/List;Ljava/util/Map;JLcom/taobao/delivery/common/transfer/query/DeliveryQueryOption;Lcom/taobao/delivery/common/mojo/MojoContext;Ljava/util/List;Ljava/util/List;)V
NEW kilim/Mailbox
DUP
INVOKESPECIAL kilim/Mailbox.()V
ASTORE11NEW com/taobao/delivery/common/kilim/FlowTask
DUP
INVOKESPECIAL com/taobao/delivery/common/kilim/FlowTask.()V
ASTORE12ALOAD1INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator;
ASTORE14GOTO L0
L1
FRAME FULL [com/taobao/delivery/common/mojo/DeliveryMojo java/util/List java/util/Map java/util/List java/util/Map J com/taobao/delivery/common/transfer/query/DeliveryQueryOption com/taobao/delivery/common/mojo/MojoContext java/util/List java/util/List kilim/Mailbox com/taobao/delivery/common/kilim/FlowTask T java/util/Iterator] []
ALOAD14INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
CHECKCAST java/lang/Long
ASTORE13GETSTATIC com/taobao/delivery/common/constant/DeliveryConstant.ignoreServices : Ljava/util/List;
ALOAD13INVOKEINTERFACE java/util/List.contains (Ljava/lang/Object;)Z
IFEQ L2
GOTO L0
L2
FRAME FULL [com/taobao/delivery/common/mojo/DeliveryMojo java/util/List java/util/Map java/util/List java/util/Map J com/taobao/delivery/common/transfer/query/DeliveryQueryOption com/taobao/delivery/common/mojo/MojoContext java/util/List java/util/List kilim/Mailbox com/taobao/delivery/common/kilim/FlowTask java/lang/Long java/util/Iterator] []
ALOAD2ALOAD13INVOKEINTERFACE java/util/Map.get (Ljava/lang/Object;)Ljava/lang/Object;
CHECKCAST com/taobao/delivery/common/dataobject/PostageDescriberDO
ASTORE15ALOAD15IFNULL L0
ALOAD15INVOKEVIRTUAL com/taobao/delivery/common/dataobject/PostageDescriberDO.getType ()Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue ()I
ICONST_1
IF_ICMPEQ L0
NEW com/taobao/delivery/common/mojo/MojoEvent
DUP
ALOAD3ALOAD4ALOAD13LLOAD5INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ALOAD7ALOAD8INVOKESPECIAL com/taobao/delivery/common/mojo/MojoEvent. (Ljava/util/List;Ljava/util/Map;Ljava/lang/Long;Ljava/lang/Long;Lcom/taobao/delivery/common/transfer/query/DeliveryQueryOption;Lcom/taobao/delivery/common/mojo/MojoContext;)V
ASTORE16NEW com/taobao/delivery/common/kilim/HandlerCalTask
DUP
ALOAD16ALOAD9ALOAD10INVOKESPECIAL com/taobao/delivery/common/kilim/HandlerCalTask. (Lcom/taobao/delivery/common/mojo/MojoEvent;Ljava/util/List;Ljava/util/List;)V
ASTORE17GETSTATIC com/taobao/delivery/common/constant/DeliveryConstant.serviceMapping : Ljava/util/Map;
ALOAD13INVOKEINTERFACE java/util/Map.get (Ljava/lang/Object;)Ljava/lang/Object;
CHECKCAST java/lang/Long
ASTORE18NEW kilim/Mailbox
DUP
INVOKESPECIAL kilim/Mailbox.()V
ASTORE19ALOAD18IFNULL L3
ALOAD1ALOAD18INVOKEINTERFACE java/util/List.contains (Ljava/lang/Object;)Z
IFEQ L3
NEW com/taobao/delivery/common/mojo/MojoEvent
DUP
ALOAD3ALOAD4ALOAD18LLOAD5INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
ALOAD7ALOAD8INVOKESPECIAL com/taobao/delivery/common/mojo/MojoEvent. (Ljava/util/List;Ljava/util/Map;Ljava/lang/Long;Ljava/lang/Long;Lcom/taobao/delivery/common/transfer/query/DeliveryQueryOption;Lcom/taobao/delivery/common/mojo/MojoContext;)V
ASTORE20NEW com/taobao/delivery/common/kilim/HandlerCalTask
DUP
ALOAD20ALOAD9ALOAD10INVOKESPECIAL com/taobao/delivery/common/kilim/HandlerCalTask. (Lcom/taobao/delivery/common/mojo/MojoEvent;Ljava/util/List;Ljava/util/List;)V
ASTORE21NEW kilim/Mailbox
DUP
INVOKESPECIAL kilim/Mailbox.()V
ASTORE22ALOAD17ALOAD22INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
ALOAD17INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.start ()Lkilim/Task;
POP
ALOAD12ALOAD21INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addSubFlowTask (Lcom/taobao/delivery/common/kilim/FlowTask;)V
ALOAD21ALOAD19INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
ALOAD21ALOAD22INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addPreTaskExtMsg (Lkilim/Mailbox;)V
GOTO L4
L3
FRAME FULL [com/taobao/delivery/common/mojo/DeliveryMojo java/util/List java/util/Map java/util/List java/util/Map J com/taobao/delivery/common/transfer/query/DeliveryQueryOption com/taobao/delivery/common/mojo/MojoContext java/util/List java/util/List kilim/Mailbox com/taobao/delivery/common/kilim/FlowTask java/lang/Long java/util/Iterator com/taobao/delivery/common/dataobject/PostageDescriberDO com/taobao/delivery/common/mojo/MojoEvent com/taobao/delivery/common/kilim/FlowTask java/lang/Long kilim/Mailbox] []
ALOAD12ALOAD17INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addSubFlowTask (Lcom/taobao/delivery/common/kilim/FlowTask;)V
ALOAD17ALOAD19INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
L4
FRAME SAME
ALOAD12ALOAD19INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addSubTaskExtMsg (Lkilim/Mailbox;)V
L0
FRAME FULL [com/taobao/delivery/common/mojo/DeliveryMojo java/util/List java/util/Map java/util/List java/util/Map J com/taobao/delivery/common/transfer/query/DeliveryQueryOption com/taobao/delivery/common/mojo/MojoContext java/util/List java/util/List kilim/Mailbox com/taobao/delivery/common/kilim/FlowTask T java/util/Iterator] []
ALOAD14INVOKEINTERFACE java/util/Iterator.hasNext ()Z
IFNE L1
ALOAD12INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.start ()Lkilim/Task;
POP
ALOAD12ALOAD11INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
ALOAD11LDC2000INVOKEVIRTUAL kilim/Mailbox.getb (J)Ljava/lang/Object;
POP
RETURN
MAXSTACK= 8MAXLOCALS= 23
MAXSTACK 是方法执行时分配的局部变量区的插槽个数。
MAXLOCALS是方法执行时操作数栈的插槽个数。
ALOAD 12的意思就是加载一个非基本类型,在局部变量区插槽序号是12的一个对象类型到操作数栈顶