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。

示例:

package pkg;
public class Bean {
    private int f;
    public int getF() {
        return this.f;
    }
    public void setF(int f) {
        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
     * @param services
     * @param describerMap
     * @param items
     * @param snapshots
     * @param areaId
     * @param option
     * @param context
     * @param fees
     * @param demoteLines
     */
    private void asynHandle(List<Long> services, Map<Long, PostageDescriberDO> describerMap, List<ItemDesc> items, Map<Long, TemplateSnapshotTO> snapshots, 
            long areaId, DeliveryQueryOption option, MojoContext context, List<FeeDesc> fees, List<DemoteLine> demoteLines) {
        Mailbox<ExitMsg> exitmb = new Mailbox<ExitMsg>();
        FlowTask resTask = new FlowTask();
        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 = new MojoEvent(items, snapshots, service, areaId, option, context);
                FlowTask preTask = new HandlerCalTask(event, fees, demoteLines);
                Long dependencyType = DeliveryConstant.serviceMapping.get(service);
                Mailbox<ExitMsg> exitFlag = new Mailbox<ExitMsg>();
                if(dependencyType != null && services.contains(dependencyType)) {
                    MojoEvent mojoEvent = new MojoEvent(items, snapshots, dependencyType, areaId, option, context);
                    FlowTask task = new HandlerCalTask(mojoEvent, fees, demoteLines);
                    Mailbox<ExitMsg> exitMsg = new Mailbox<ExitMsg>();
                    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.<init> ()V
    ASTORE 11
    NEW com/taobao/delivery/common/kilim/FlowTask
    DUP
    INVOKESPECIAL com/taobao/delivery/common/kilim/FlowTask.<init> ()V
    ASTORE 12
    ALOAD 1
    INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator;
    ASTORE 14
    GOTO 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] []
    ALOAD 14
    INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object;
    CHECKCAST java/lang/Long
    ASTORE 13
    GETSTATIC com/taobao/delivery/common/constant/DeliveryConstant.ignoreServices : Ljava/util/List;
    ALOAD 13
    INVOKEINTERFACE 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] []
    ALOAD 2
    ALOAD 13
    INVOKEINTERFACE java/util/Map.get (Ljava/lang/Object;)Ljava/lang/Object;
    CHECKCAST com/taobao/delivery/common/dataobject/PostageDescriberDO
    ASTORE 15
    ALOAD 15
    IFNULL L0
    ALOAD 15
    INVOKEVIRTUAL 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
    ALOAD 3
    ALOAD 4
    ALOAD 13
    LLOAD 5
    INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
    ALOAD 7
    ALOAD 8
    INVOKESPECIAL com/taobao/delivery/common/mojo/MojoEvent.<init> (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
    ASTORE 16
    NEW com/taobao/delivery/common/kilim/HandlerCalTask
    DUP
    ALOAD 16
    ALOAD 9
    ALOAD 10
    INVOKESPECIAL com/taobao/delivery/common/kilim/HandlerCalTask.<init> (Lcom/taobao/delivery/common/mojo/MojoEvent;Ljava/util/List;Ljava/util/List;)V
    ASTORE 17
    GETSTATIC com/taobao/delivery/common/constant/DeliveryConstant.serviceMapping : Ljava/util/Map;
    ALOAD 13
    INVOKEINTERFACE java/util/Map.get (Ljava/lang/Object;)Ljava/lang/Object;
    CHECKCAST java/lang/Long
    ASTORE 18
    NEW kilim/Mailbox
    DUP
    INVOKESPECIAL kilim/Mailbox.<init> ()V
    ASTORE 19
    ALOAD 18
    IFNULL L3
    ALOAD 1
    ALOAD 18
    INVOKEINTERFACE java/util/List.contains (Ljava/lang/Object;)Z
    IFEQ L3
    NEW com/taobao/delivery/common/mojo/MojoEvent
    DUP
    ALOAD 3
    ALOAD 4
    ALOAD 18
    LLOAD 5
    INVOKESTATIC java/lang/Long.valueOf (J)Ljava/lang/Long;
    ALOAD 7
    ALOAD 8
    INVOKESPECIAL com/taobao/delivery/common/mojo/MojoEvent.<init> (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
    ASTORE 20
    NEW com/taobao/delivery/common/kilim/HandlerCalTask
    DUP
    ALOAD 20
    ALOAD 9
    ALOAD 10
    INVOKESPECIAL com/taobao/delivery/common/kilim/HandlerCalTask.<init> (Lcom/taobao/delivery/common/mojo/MojoEvent;Ljava/util/List;Ljava/util/List;)V
    ASTORE 21
    NEW kilim/Mailbox
    DUP
    INVOKESPECIAL kilim/Mailbox.<init> ()V
    ASTORE 22
    ALOAD 17
    ALOAD 22
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
    ALOAD 17
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.start ()Lkilim/Task;
    POP
    ALOAD 12
    ALOAD 21
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addSubFlowTask (Lcom/taobao/delivery/common/kilim/FlowTask;)V
    ALOAD 21
    ALOAD 19
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
    ALOAD 21
    ALOAD 22
    INVOKEVIRTUAL 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] []
    ALOAD 12
    ALOAD 17
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.addSubFlowTask (Lcom/taobao/delivery/common/kilim/FlowTask;)V
    ALOAD 17
    ALOAD 19
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
   L4
   FRAME SAME
    ALOAD 12
    ALOAD 19
    INVOKEVIRTUAL 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] []
    ALOAD 14
    INVOKEINTERFACE java/util/Iterator.hasNext ()Z
    IFNE L1
    ALOAD 12
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.start ()Lkilim/Task;
    POP
    ALOAD 12
    ALOAD 11
    INVOKEVIRTUAL com/taobao/delivery/common/kilim/FlowTask.informOnExit (Lkilim/Mailbox;)V
    ALOAD 11
    LDC 2000
    INVOKEVIRTUAL kilim/Mailbox.getb (J)Ljava/lang/Object;
    POP
    RETURN
    MAXSTACK = 8
    MAXLOCALS = 23


MAXSTACK 是方法执行时分配的局部变量区的插槽个数。
MAXLOCALS 是方法执行时操作数栈的插槽个数。
ALOAD 12的意思就是加载一个非基本类型,在局部变量区插槽序号是12的一个对象类型到操作数栈顶


posted on 2013-11-20 19:28  xuqiyu  阅读(843)  评论(1编辑  收藏  举报