<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-204  評論-149  文章-0  trackbacks-0

    這個最接近之前提出的API轉換問題
    這個需要掃描源代碼找到此類的方法調用處,然后在方法調用處的前后添加指令
    即將代碼轉換成如下形式:


    public class StringBuilder
    {
        
    public String buildString(int length) {

            String result 
    = "";
            
    for (int i = 0; i < length; i++{
                result 
    += (char)(i%26 + 'a');
            }


            
    return result;
        }

        
        
        
    public static void main(String[] argv) {
            StringBuilder inst 
    = new StringBuilder();
            
    for (int i = 0; i < argv.length; i++{
                
                long start = System.currentTimeMillis();

                String result 
    = inst.buildString(Integer.parseInt(argv[i]));
                System.out.println("Call to buildString$impl took " +
                        (System.currentTimeMillis()-start) + " ms.");

                
                System.out.println(
    "Constructed string of length " +
                    result.length());
            }

        }

    }



    轉換代碼如下:
    先掃描這個類中的各個方法
    我準備改變一下生成策略,不自己寫指令了,這個自己寫指令比較麻煩,但要加的代碼比較多時比較容易出錯,當所加的代碼有if,跳轉語句,自己根本就不會如何寫添哪些指令,這種寫類似匯編指令總是很麻煩的。

    先要把加的代碼自己在某個類中事先用方法寫好,實例方法也好,靜態方法也好,方法帶有參數或者有返回值,
    這些參數和返回值供調用方法中的局部變量來替換和使用。
    再要添加代碼的方法的前后調用這些已經寫好的方法的字節碼的指令序列生成InstructionList,然后再添加到使用這個方法的指令序列中

    如下

    public class ToolUtil {
        
        
    public static long printStart() {
            System.out.println(
    "start start start start");
            
    long start = System.currentTimeMillis();
            
    return start;
        }

        
        
    public static void printEnd(String methodname,long start){
            
            System.out.println(
    "Call to "+methodname+" took " +
                    (System.currentTimeMillis()
    -start) + " ms.");
            System.out.println(
    "end end end end end end");
        }


    }


    原始的方法
    public class StringBuilder {
        
        
        
    /*
         * 要在調用了此方法的方法的代碼的前后添加代碼
         
    */

        
    public String buildString(int length) {

            String result 
    = "";
            
    for (int i = 0; i < length; i++{
                result 
    += (char) (i % 26 + 'a');
            }

            System.out.println(result);

            
    return result;
        }


        
    /*
         * 調用了buildString方法
         
    */

        
    private String testInvokeMethod(){
            
            String temp 
    = null;
            
            temp 
    = buildString(10);
            
    return temp;

        }




        
    /*
         * 調用了buildString方法
         
    */

        
    public static void main(String[] argv) {
            StringBuilder inst 
    = new StringBuilder();
            
    for (int i = 0; i < argv.length; i++{
                
                String result 
    = inst.buildString(Integer.parseInt(argv[i]));
                
                System.out.println(
    "Constructed string of length "
                        
    + result.length());
            }

        }

    }


    生成的方法為
    public class StringBuilder {
        
        
        
    /*
         * 要在調用了此方法的方法的代碼的前后添加代碼
         
    */

        
    public String buildString(int length) {

            String result 
    = "";
            
    for (int i = 0; i < length; i++{
                result 
    += (char) (i % 26 + 'a');
            }

            System.out.println(result);

            
    return result;
        }


        
    /*
         * 調用了buildString方法
         
    */

        
    private String testInvokeMethod(){
            
            String temp 
    = null;
            //調用事先寫好的方法
            long startTime = ToolUtil.printStart();
            
            temp 
    = buildString(10);
            
    //調用事先寫好的方法
            ToolUtil.printEnd("buildString", startTime);

            
            System.out.println(
    "我是測試方法,我是測試方法,我是測試方法,我是測試方法");
            
    return temp;

        }




        
    /*
         * 調用了buildString方法
         
    */

        
    public static void main(String[] argv) {
            StringBuilder inst 
    = new StringBuilder();
            
    for (int i = 0; i < argv.length; i++{
                
                //調用事先寫好的方法
                long startTime = ToolUtil.printStart();

                String result 
    = inst.buildString(Integer.parseInt(argv[i]));
                
    //調用事先寫好的方法
                ToolUtil.printEnd("buildString", startTime);

                
                System.out.println(
    "Constructed string of length "
                        
    + result.length());
            }

        }

    }

    main這個調用的代碼或者使用INVOKEXXXX指令實現,或者把這些調用方法的字節碼指令序列加入到main的指令序列當中來實現,直接加的話可能自己事先寫的方法的局部變量與main方法的局部變量會相同,而且涉及到所加的指令序列使用局部變量的問題,比如加的iload_0,istore_2就會引用現在方法的局部變量,但是現在的局部變量根本就不是這種指令所對應的類型
    。所以還是使用方法調用比較方便


    import java.io.FileOutputStream;

    import org.apache.bcel.Constants;
    import org.apache.bcel.classfile.ClassParser;
    import org.apache.bcel.classfile.ConstantClass;
    import org.apache.bcel.classfile.ConstantMethodref;
    import org.apache.bcel.classfile.ConstantNameAndType;
    import org.apache.bcel.classfile.ConstantPool;
    import org.apache.bcel.classfile.JavaClass;
    import org.apache.bcel.classfile.Method;
    import org.apache.bcel.generic.ClassGen;
    import org.apache.bcel.generic.ConstantPoolGen;
    import org.apache.bcel.generic.INVOKEVIRTUAL;
    import org.apache.bcel.generic.Instruction;
    import org.apache.bcel.generic.InstructionFactory;
    import org.apache.bcel.generic.InstructionHandle;
    import org.apache.bcel.generic.InstructionList;
    import org.apache.bcel.generic.LocalVariableGen;
    import org.apache.bcel.generic.MethodGen;
    import org.apache.bcel.generic.Type;


    public class BCELTiming3 {
        
        
        
        
    /*
         * 掃描StringBuilder的各個方法的指令序列,在其中找Invokexxxx指令,
         * 看此指令在常量池中引用的方法引用是否是要其前后加代碼的方法
         * 方法所在的類要一致,方法的名稱要一致,方法的簽名要一致
         * 
         
    */

        
        
    /**
         * 
         * 
    @param cgen 要被解析的類class文件
         * 
    @param classname 要被修改的方法所在的類名稱,若有包名,則為java/lang/Object類似的
         * 
    @param methodname 要被修改的方法的名稱
         * 
    @param methodSignature 要被修改的方法的簽名
         
    */

        
    private static void modifyWrapper(ClassGen cgen,String classname,String methodname,String methodSignature){
            
            InstructionFactory ifact 
    = new InstructionFactory(cgen);
            ConstantPoolGen pgen 
    = cgen.getConstantPool();
            ConstantPool pool 
    = pgen.getConstantPool();
            
            String cname 
    = cgen.getClassName();
            
            
            
            Method[] methods 
    = cgen.getMethods();
            
    for(int i=0;i<methods.length;i++){
                Method tempMethod 
    = methods[i];
                
                MethodGen tempMethodGen 
    = new MethodGen(tempMethod,cname,pgen);
                
                InstructionList tempList 
    = tempMethodGen.getInstructionList();
                tempList.iterator();
                Instruction[] tempInstructions 
    = tempList.getInstructions();
                InstructionHandle[] tempInHandles 
    = tempList.getInstructionHandles();
                
    for(int j=0;j<tempInHandles.length;j++){
                    InstructionHandle ihandle 
    = tempInHandles[j];
                    Instruction nowInstruction 
    = ihandle.getInstruction();
                    
    if(nowInstruction.getOpcode()==Constants.INVOKEVIRTUAL){
                        INVOKEVIRTUAL invokeVirtual 
    = (INVOKEVIRTUAL)nowInstruction;
                        ConstantMethodref cmr 
    = (ConstantMethodref)pgen.getConstant(invokeVirtual.getIndex());
                        
                        ConstantClass cc 
    = (ConstantClass)pgen.getConstant(cmr.getClassIndex());
                        String nowClassName 
    = cc.getBytes(pgen.getConstantPool());
                        ConstantNameAndType cnt 
    = (ConstantNameAndType)pgen.getConstant(cmr.getNameAndTypeIndex());
                        String nowMethodName 
    = cnt.getName(pgen.getConstantPool());
                        String nowMethodSignature 
    = cnt.getSignature(pgen.getConstantPool());
                        
                        
    //判斷此方法的所屬的類,方法的名稱,方法的簽名是否與所要加的一致(I)Ljava/lang/String;
                        if(nowClassName.equals(classname) && nowMethodName.equals(methodname) && nowMethodSignature.equals(methodSignature)){
                            
                            cgen.removeMethod(tempMethodGen.getMethod());
                            
                            
    //找到此方法在list的位置
                            InstructionList beforeList = new InstructionList();
                            
    //先加一個局部變量保存starttime的值
                            LocalVariableGen lvg = tempMethodGen.addLocalVariable("starttime", Type.LONG, nullnull);
                            beforeList.append(ifact.createInvoke(
    "ToolUtil""printStart", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
                            beforeList.append(InstructionFactory.createStore(Type.LONG, lvg.getIndex()));
                            tempList.insert(ihandle.getPrev().getPrev(), beforeList);
                            
                            
    //加方法后的代碼
                            InstructionList afterList = new InstructionList();
                            afterList.append(ifact.createConstant(methodname));
                            afterList.append(ifact.createLoad(Type.LONG, lvg.getIndex()));
                            afterList.append(ifact.createInvoke(
    "ToolUtil""printEnd", Type.VOID, new Type[]{Type.STRING,Type.LONG}, Constants.INVOKESTATIC));
                            tempList.insert(ihandle.getNext().getNext(), afterList);
                            
                            
                            
    //finalize the construted method
                            tempMethodGen.stripAttributes(false);
                            tempMethodGen.setMaxStack();
                            tempMethodGen.setMaxLocals();

                            cgen.addMethod(tempMethodGen.getMethod());
                            
                            System.out.println(tempMethodGen.getInstructionList());
                            System.out.println();
                            System.out.println();
                            
                            
                        }

                    }

                }

                
    //            tempList.setPositions();
    //            tempList.findHandle(pos);
                
            }

                
        }


        
    /**
         * 
    @param args
         
    */

        
    public static void main(String[] args) {
            
            args[
    0]="D:\\java to eclipse\\javaeclipsestudy\\workspace\\BCELTest\\bin\\StringBuilder.class";
            
            
    if(args.length==1 && args[0].endsWith(".class")){
                
    try{
                    JavaClass jclas 
    = new ClassParser(args[0]).parse();
                    
                    ClassGen cgen 
    = new ClassGen(jclas);
                    
                    modifyWrapper(cgen,
    "StringBuilder","buildString","(I)Ljava/lang/String;");
                    
                    
                    cgen.getJavaClass().dump(args[
    0]);
                }
    catch(Exception e){
                    e.printStackTrace();
                }

            }
    else{
                System.out.println(
    "usage: class-file");
            }


        }


    }



    posted on 2009-08-13 23:10 Frank_Fang 閱讀(1729) 評論(3)  編輯  收藏 所屬分類: bcel javassist

    評論:
    # re: 用 BCEL 設計字節碼(三)直接在方法的調用處添加方法 2009-08-16 18:37 | Frank_Fang
    原來方法的字節碼
    --------------------------------33
    --------------------------------33
    0
    2
    CONSTANT_Utf8[1]("SourceFile")
    true
    CONSTANT_Utf8[1]("StringBuilder.java")
    1
    StringBuilder.java
    StringBuilder.java
    ---------------------------------------------------------------------------
    1:CONSTANT_Class[7](name_index = 2)
    2:CONSTANT_Utf8[1]("StringBuilder")
    3:CONSTANT_Class[7](name_index = 4)
    4:CONSTANT_Utf8[1]("java/lang/Object")
    5:CONSTANT_Utf8[1]("<init>")
    6:CONSTANT_Utf8[1]("()V")
    7:CONSTANT_Utf8[1]("Code")
    8:CONSTANT_Methodref[10](class_index = 3, name_and_type_index = 9)
    9:CONSTANT_NameAndType[12](name_index = 5, signature_index = 6)
    10:CONSTANT_Utf8[1]("LineNumberTable")
    11:CONSTANT_Utf8[1]("LocalVariableTable")
    12:CONSTANT_Utf8[1]("this")
    13:CONSTANT_Utf8[1]("LStringBuilder;")
    14:CONSTANT_Utf8[1]("buildString")
    15:CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
    16:CONSTANT_String[8](string_index = 17)
    17:CONSTANT_Utf8[1]("")
    18:CONSTANT_Class[7](name_index = 19)
    19:CONSTANT_Utf8[1]("java/lang/StringBuilder")
    20:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 23)
    21:CONSTANT_Class[7](name_index = 22)
    22:CONSTANT_Utf8[1]("java/lang/String")
    23:CONSTANT_NameAndType[12](name_index = 24, signature_index = 25)
    24:CONSTANT_Utf8[1]("valueOf")
    25:CONSTANT_Utf8[1]("(Ljava/lang/Object;)Ljava/lang/String;")
    26:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 27)
    27:CONSTANT_NameAndType[12](name_index = 5, signature_index = 28)
    28:CONSTANT_Utf8[1]("(Ljava/lang/String;)V")
    29:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 30)
    30:CONSTANT_NameAndType[12](name_index = 31, signature_index = 32)
    31:CONSTANT_Utf8[1]("append")
    32:CONSTANT_Utf8[1]("(C)Ljava/lang/StringBuilder;")
    33:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 34)
    34:CONSTANT_NameAndType[12](name_index = 35, signature_index = 36)
    35:CONSTANT_Utf8[1]("toString")
    36:CONSTANT_Utf8[1]("()Ljava/lang/String;")
    37:CONSTANT_Fieldref[9](class_index = 38, name_and_type_index = 40)
    *********************ConstantFieldref start**********************
    cc.toString : CONSTANT_Class[7](name_index = 39)
    java/lang/System
    cnat.toString : CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
    out
    Ljava/io/PrintStream;
    **********************ConstantFieldref end*******************************
    38:CONSTANT_Class[7](name_index = 39)
    39:CONSTANT_Utf8[1]("java/lang/System")
    40:CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
    41:CONSTANT_Utf8[1]("out")
    42:CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
    43:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 46)
    44:CONSTANT_Class[7](name_index = 45)
    45:CONSTANT_Utf8[1]("java/io/PrintStream")
    46:CONSTANT_NameAndType[12](name_index = 47, signature_index = 28)
    47:CONSTANT_Utf8[1]("println")
    48:CONSTANT_Utf8[1]("length")
    49:CONSTANT_Utf8[1]("I")
    50:CONSTANT_Utf8[1]("result")
    51:CONSTANT_Utf8[1]("Ljava/lang/String;")
    52:CONSTANT_Utf8[1]("i")
    53:CONSTANT_Utf8[1]("testInvokeMethod")
    54:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 55)
    55:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
    56:CONSTANT_String[8](string_index = 57)
    57:CONSTANT_Utf8[1]("我是測試方法,我是測試方法,我是測試方法,我是測試方法")
    58:CONSTANT_Utf8[1]("temp")
    59:CONSTANT_Utf8[1]("main")
    60:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
    61:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
    62:CONSTANT_Methodref[10](class_index = 63, name_and_type_index = 65)
    63:CONSTANT_Class[7](name_index = 64)
    64:CONSTANT_Utf8[1]("java/lang/Integer")
    65:CONSTANT_NameAndType[12](name_index = 66, signature_index = 67)
    66:CONSTANT_Utf8[1]("parseInt")
    67:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
    68:CONSTANT_String[8](string_index = 69)
    69:CONSTANT_Utf8[1]("Constructed string of length ")
    70:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 71)
    71:CONSTANT_NameAndType[12](name_index = 48, signature_index = 72)
    72:CONSTANT_Utf8[1]("()I")
    73:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 74)
    74:CONSTANT_NameAndType[12](name_index = 31, signature_index = 75)
    75:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
    76:CONSTANT_Utf8[1]("argv")
    77:CONSTANT_Utf8[1]("[Ljava/lang/String;")
    78:CONSTANT_Utf8[1]("inst")
    79:CONSTANT_Utf8[1]("SourceFile")
    80:CONSTANT_Utf8[1]("StringBuilder.java")
    --------------------------域----------------------------
    -----------域的長度,此類定義的成員變量的個數-------------0




    start method method method-----------------------------------
    方法訪問標志
    1
    方法訪問名稱
    <init>
    CONSTANT_Utf8[1]("<init>")
    方法簽名
    ()V
    CONSTANT_Utf8[1]("()V")
    方法的參數類型
    方法的返回類型
    void
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 47
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 5
    給出該方法在執行中任何點操作數棧上字的最大個數 1
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 1
    code的字節信息調用code.getCode()返回byte[] [B@1571886
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======1
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=5| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    完整的code.toString的信息
    public void <init>()
    Code(max_stack = 1, max_locals = 1, code_length = 5)
    0: aload_0
    1: invokespecial java.lang.Object.<init> ()V (8)
    4: return

    Attribute(s) =
    LineNumber(0, 1)
    LocalVariable(start_pc = 0, length = 5, index = 0:StringBuilder this)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    1
    方法訪問名稱
    buildString
    CONSTANT_Utf8[1]("buildString")
    方法簽名
    (I)Ljava/lang/String;
    CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
    方法的參數類型
    int方法的返回類型
    java.lang.String
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 143
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 51
    給出該方法在執行中任何點操作數棧上字的最大個數 3
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 4
    code的字節信息調用code.getCode()返回byte[] [B@1c184f4
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======4
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=48 | lv.getName()=length| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=1
    --------------------第 2 個局部變量的信息
    lv.getStartPC()=3| lv.getLength=48| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=2
    --------------------第 3 個局部變量的信息
    lv.getStartPC()=5| lv.getLength=37| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=3
    完整的code.toString的信息
    public String buildString(int length)
    Code(max_stack = 3, max_locals = 4, code_length = 51)
    0: ldc "" (16)
    2: astore_2
    3: iconst_0
    4: istore_3
    5: goto #37
    8: new <java.lang.StringBuilder> (18)
    11: dup
    12: aload_2
    13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
    16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    19: iload_3
    20: bipush 26
    22: irem
    23: bipush 97
    25: iadd
    26: i2c
    27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
    30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    33: astore_2
    34: iinc %3 1
    37: iload_3
    38: iload_1
    39: if_icmplt #8
    42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    45: aload_2
    46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    49: aload_2
    50: areturn

    Attribute(s) =
    LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
    LineNumber(42, 13), LineNumber(49, 15)
    LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
    LocalVariable(start_pc = 0, length = 51, index = 1:int length)
    LocalVariable(start_pc = 3, length = 48, index = 2:String result)
    LocalVariable(start_pc = 5, length = 37, index = 3:int i)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    2
    方法訪問名稱
    testInvokeMethod
    CONSTANT_Utf8[1]("testInvokeMethod")
    方法簽名
    ()Ljava/lang/String;
    CONSTANT_Utf8[1]("()Ljava/lang/String;")
    方法的參數類型
    方法的返回類型
    java.lang.String
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 83
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 19
    給出該方法在執行中任何點操作數棧上字的最大個數 2
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 2
    code的字節信息調用code.getCode()返回byte[] [B@1ffbd68
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======2
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=19| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=2| lv.getLength=17| lv.getNameIndex()=58 | lv.getName()=temp| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=1
    完整的code.toString的信息
    private String testInvokeMethod()
    Code(max_stack = 2, max_locals = 2, code_length = 19)
    0: aconst_null
    1: astore_1
    2: aload_0
    3: bipush 10
    5: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
    8: astore_1
    9: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    12: ldc "我是測試方法,我是測試方法,我是測試方法,我是測試方法" (56)
    14: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    17: aload_1
    18: areturn

    Attribute(s) =
    LineNumber(0, 27), LineNumber(2, 31), LineNumber(9, 35), LineNumber(17, 37)

    LocalVariable(start_pc = 0, length = 19, index = 0:StringBuilder this)
    LocalVariable(start_pc = 2, length = 17, index = 1:String temp)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    9
    方法訪問名稱
    main
    CONSTANT_Utf8[1]("main")
    方法簽名
    ([Ljava/lang/String;)V
    CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
    方法的參數類型
    java.lang.String[]方法的返回類型
    void
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 159
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 59
    給出該方法在執行中任何點操作數棧上字的最大個數 4
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 4
    code的字節信息調用code.getCode()返回byte[] [B@ec16a4
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======4
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=59| lv.getNameIndex()=76 | lv.getName()=argv| lv.getSignatureIndex()=77 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=8| lv.getLength=51| lv.getNameIndex()=78 | lv.getName()=inst| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=1
    --------------------第 2 個局部變量的信息
    lv.getStartPC()=10| lv.getLength=48| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=2
    --------------------第 3 個局部變量的信息
    lv.getStartPC()=24| lv.getLength=25| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=3
    完整的code.toString的信息
    public static void main(String[] argv)
    Code(max_stack = 4, max_locals = 4, code_length = 59)
    0: new <StringBuilder> (1)
    3: dup
    4: invokespecial StringBuilder.<init> ()V (61)
    7: astore_1
    8: iconst_0
    9: istore_2
    10: goto #52
    13: aload_1
    14: aload_0
    15: iload_2
    16: aaload
    17: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (62)
    20: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
    23: astore_3
    24: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    27: new <java.lang.StringBuilder> (18)
    30: dup
    31: ldc "Constructed string of length " (68)
    33: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    36: aload_3
    37: invokevirtual java.lang.String.length ()I (70)
    40: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (73)
    43: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    49: iinc %2 1
    52: iload_2
    53: aload_0
    54: arraylength
    55: if_icmplt #13
    58: return

    Attribute(s) =
    LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 52), LineNumber(24, 56),
    LineNumber(36, 57), LineNumber(46, 56), LineNumber(49, 48), LineNumber(58, 59)

    LocalVariable(start_pc = 0, length = 59, index = 0:String[] argv)
    LocalVariable(start_pc = 8, length = 51, index = 1:StringBuilder inst)
    LocalVariable(start_pc = 10, length = 48, index = 2:int i)
    LocalVariable(start_pc = 24, length = 25, index = 3:String result)

    end method method method-----------------------------------


      回復  更多評論
      
    # re: 用 BCEL 設計字節碼(三)直接在方法的調用處添加方法 2009-08-16 18:39 | Frank_Fang
    自己在程序加調用語句用編譯器生成的字節碼
    --------------------------------33
    --------------------------------33
    0
    2
    CONSTANT_Utf8[1]("SourceFile")
    true
    CONSTANT_Utf8[1]("StringBuilder.java")
    1
    StringBuilder.java
    StringBuilder.java
    ---------------------------------------------------------------------------
    1:CONSTANT_Class[7](name_index = 2)
    2:CONSTANT_Utf8[1]("StringBuilder")
    3:CONSTANT_Class[7](name_index = 4)
    4:CONSTANT_Utf8[1]("java/lang/Object")
    5:CONSTANT_Utf8[1]("<init>")
    6:CONSTANT_Utf8[1]("()V")
    7:CONSTANT_Utf8[1]("Code")
    8:CONSTANT_Methodref[10](class_index = 3, name_and_type_index = 9)
    9:CONSTANT_NameAndType[12](name_index = 5, signature_index = 6)
    10:CONSTANT_Utf8[1]("LineNumberTable")
    11:CONSTANT_Utf8[1]("LocalVariableTable")
    12:CONSTANT_Utf8[1]("this")
    13:CONSTANT_Utf8[1]("LStringBuilder;")
    14:CONSTANT_Utf8[1]("buildString")
    15:CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
    16:CONSTANT_String[8](string_index = 17)
    17:CONSTANT_Utf8[1]("")
    18:CONSTANT_Class[7](name_index = 19)
    19:CONSTANT_Utf8[1]("java/lang/StringBuilder")
    20:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 23)
    21:CONSTANT_Class[7](name_index = 22)
    22:CONSTANT_Utf8[1]("java/lang/String")
    23:CONSTANT_NameAndType[12](name_index = 24, signature_index = 25)
    24:CONSTANT_Utf8[1]("valueOf")
    25:CONSTANT_Utf8[1]("(Ljava/lang/Object;)Ljava/lang/String;")
    26:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 27)
    27:CONSTANT_NameAndType[12](name_index = 5, signature_index = 28)
    28:CONSTANT_Utf8[1]("(Ljava/lang/String;)V")
    29:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 30)
    30:CONSTANT_NameAndType[12](name_index = 31, signature_index = 32)
    31:CONSTANT_Utf8[1]("append")
    32:CONSTANT_Utf8[1]("(C)Ljava/lang/StringBuilder;")
    33:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 34)
    34:CONSTANT_NameAndType[12](name_index = 35, signature_index = 36)
    35:CONSTANT_Utf8[1]("toString")
    36:CONSTANT_Utf8[1]("()Ljava/lang/String;")
    37:CONSTANT_Fieldref[9](class_index = 38, name_and_type_index = 40)
    *********************ConstantFieldref start**********************
    cc.toString : CONSTANT_Class[7](name_index = 39)
    java/lang/System
    cnat.toString : CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
    out
    Ljava/io/PrintStream;
    **********************ConstantFieldref end*******************************
    38:CONSTANT_Class[7](name_index = 39)
    39:CONSTANT_Utf8[1]("java/lang/System")
    40:CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
    41:CONSTANT_Utf8[1]("out")
    42:CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
    43:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 46)
    44:CONSTANT_Class[7](name_index = 45)
    45:CONSTANT_Utf8[1]("java/io/PrintStream")
    46:CONSTANT_NameAndType[12](name_index = 47, signature_index = 28)
    47:CONSTANT_Utf8[1]("println")
    48:CONSTANT_Utf8[1]("length")
    49:CONSTANT_Utf8[1]("I")
    50:CONSTANT_Utf8[1]("result")
    51:CONSTANT_Utf8[1]("Ljava/lang/String;")
    52:CONSTANT_Utf8[1]("i")
    53:CONSTANT_Utf8[1]("testInvokeMethod")
    54:CONSTANT_Methodref[10](class_index = 55, name_and_type_index = 57)
    55:CONSTANT_Class[7](name_index = 56)
    56:CONSTANT_Utf8[1]("ToolUtil")
    57:CONSTANT_NameAndType[12](name_index = 58, signature_index = 59)
    58:CONSTANT_Utf8[1]("printStart")
    59:CONSTANT_Utf8[1]("()J")
    60:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 61)
    61:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
    62:CONSTANT_String[8](string_index = 14)
    63:CONSTANT_Methodref[10](class_index = 55, name_and_type_index = 64)
    64:CONSTANT_NameAndType[12](name_index = 65, signature_index = 66)
    65:CONSTANT_Utf8[1]("printEnd")
    66:CONSTANT_Utf8[1]("(Ljava/lang/String;J)V")
    67:CONSTANT_String[8](string_index = 68)
    68:CONSTANT_Utf8[1]("我是測試方法,我是測試方法,我是測試方法,我是測試方法")
    69:CONSTANT_Utf8[1]("temp")
    70:CONSTANT_Utf8[1]("startTime")
    71:CONSTANT_Utf8[1]("J")
    72:CONSTANT_Utf8[1]("main")
    73:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
    74:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
    75:CONSTANT_Methodref[10](class_index = 76, name_and_type_index = 78)
    76:CONSTANT_Class[7](name_index = 77)
    77:CONSTANT_Utf8[1]("java/lang/Integer")
    78:CONSTANT_NameAndType[12](name_index = 79, signature_index = 80)
    79:CONSTANT_Utf8[1]("parseInt")
    80:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
    81:CONSTANT_String[8](string_index = 82)
    82:CONSTANT_Utf8[1]("Constructed string of length ")
    83:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 84)
    84:CONSTANT_NameAndType[12](name_index = 48, signature_index = 85)
    85:CONSTANT_Utf8[1]("()I")
    86:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 87)
    87:CONSTANT_NameAndType[12](name_index = 31, signature_index = 88)
    88:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
    89:CONSTANT_Utf8[1]("argv")
    90:CONSTANT_Utf8[1]("[Ljava/lang/String;")
    91:CONSTANT_Utf8[1]("inst")
    92:CONSTANT_Utf8[1]("SourceFile")
    93:CONSTANT_Utf8[1]("StringBuilder.java")
    --------------------------域----------------------------
    -----------域的長度,此類定義的成員變量的個數-------------0




    start method method method-----------------------------------
    方法訪問標志
    1
    方法訪問名稱
    <init>
    CONSTANT_Utf8[1]("<init>")
    方法簽名
    ()V
    CONSTANT_Utf8[1]("()V")
    方法的參數類型
    方法的返回類型
    void
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 47
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 5
    給出該方法在執行中任何點操作數棧上字的最大個數 1
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 1
    code的字節信息調用code.getCode()返回byte[] [B@1571886
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======1
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=5| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    完整的code.toString的信息
    public void <init>()
    Code(max_stack = 1, max_locals = 1, code_length = 5)
    0: aload_0
    1: invokespecial java.lang.Object.<init> ()V (8)
    4: return

    Attribute(s) =
    LineNumber(0, 1)
    LocalVariable(start_pc = 0, length = 5, index = 0:StringBuilder this)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    1
    方法訪問名稱
    buildString
    CONSTANT_Utf8[1]("buildString")
    方法簽名
    (I)Ljava/lang/String;
    CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
    方法的參數類型
    int方法的返回類型
    java.lang.String
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 143
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 51
    給出該方法在執行中任何點操作數棧上字的最大個數 3
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 4
    code的字節信息調用code.getCode()返回byte[] [B@1c184f4
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======4
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=48 | lv.getName()=length| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=1
    --------------------第 2 個局部變量的信息
    lv.getStartPC()=3| lv.getLength=48| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=2
    --------------------第 3 個局部變量的信息
    lv.getStartPC()=5| lv.getLength=37| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=3
    完整的code.toString的信息
    public String buildString(int length)
    Code(max_stack = 3, max_locals = 4, code_length = 51)
    0: ldc "" (16)
    2: astore_2
    3: iconst_0
    4: istore_3
    5: goto #37
    8: new <java.lang.StringBuilder> (18)
    11: dup
    12: aload_2
    13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
    16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    19: iload_3
    20: bipush 26
    22: irem
    23: bipush 97
    25: iadd
    26: i2c
    27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
    30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    33: astore_2
    34: iinc %3 1
    37: iload_3
    38: iload_1
    39: if_icmplt #8
    42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    45: aload_2
    46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    49: aload_2
    50: areturn

    Attribute(s) =
    LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
    LineNumber(42, 13), LineNumber(49, 15)
    LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
    LocalVariable(start_pc = 0, length = 51, index = 1:int length)
    LocalVariable(start_pc = 3, length = 48, index = 2:String result)
    LocalVariable(start_pc = 5, length = 37, index = 3:int i)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    2
    方法訪問名稱
    testInvokeMethod
    CONSTANT_Utf8[1]("testInvokeMethod")
    方法簽名
    ()Ljava/lang/String;
    CONSTANT_Utf8[1]("()Ljava/lang/String;")
    方法的參數類型
    方法的返回類型
    java.lang.String
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 111
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 29
    給出該方法在執行中任何點操作數棧上字的最大個數 3
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 4
    code的字節信息調用code.getCode()返回byte[] [B@1ffbd68
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======3
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=29| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=2| lv.getLength=27| lv.getNameIndex()=69 | lv.getName()=temp| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=1
    --------------------第 2 個局部變量的信息
    lv.getStartPC()=6| lv.getLength=23| lv.getNameIndex()=70 | lv.getName()=startTime| lv.getSignatureIndex()=71 | lv.getSignature()=J |lv.getIndex()=2
    完整的code.toString的信息
    private String testInvokeMethod()
    Code(max_stack = 3, max_locals = 4, code_length = 29)
    0: aconst_null
    1: astore_1
    2: invokestatic ToolUtil.printStart ()J (54)
    5: lstore_2
    6: aload_0
    7: bipush 10
    9: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (60)
    12: astore_1
    13: ldc "buildString" (62)
    15: lload_2
    16: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (63)
    19: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    22: ldc "我是測試方法,我是測試方法,我是測試方法,我是測試方法" (67)
    24: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    27: aload_1
    28: areturn

    Attribute(s) =
    LineNumber(0, 27), LineNumber(2, 29), LineNumber(6, 31), LineNumber(13, 33),
    LineNumber(19, 35), LineNumber(27, 37)
    LocalVariable(start_pc = 0, length = 29, index = 0:StringBuilder this)
    LocalVariable(start_pc = 2, length = 27, index = 1:String temp)
    LocalVariable(start_pc = 6, length = 23, index = 2:long startTime)

    end method method method-----------------------------------


    start method method method-----------------------------------
    方法訪問標志
    9
    方法訪問名稱
    main
    CONSTANT_Utf8[1]("main")
    方法簽名
    ([Ljava/lang/String;)V
    CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
    方法的參數類型
    java.lang.String[]方法的返回類型
    void
    方法的ExceptionTable屬性----------方法的throws聲明的異常信息------------------------
    exceptionTable==null true
    方法的Code---------------------------------------------
    7
    CONSTANT_Utf8[1]("Code")
    code.getLength() 屬性結構中attribute length 的長度 189
    code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 71
    給出該方法在執行中任何點操作數棧上字的最大個數 4
    給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 6
    code的字節信息調用code.getCode()返回byte[] [B@ec16a4
    ce.length===========0
    code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
    方法的Code的LineNumberTable
    方法的Code的LocalVariableTable
    LocalVariableTable
    localvariableTable==null false
    lvs==null false
    lvs.length======5
    --------------------第 0 個局部變量的信息
    lv.getStartPC()=0| lv.getLength=71| lv.getNameIndex()=89 | lv.getName()=argv| lv.getSignatureIndex()=90 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
    --------------------第 1 個局部變量的信息
    lv.getStartPC()=8| lv.getLength=63| lv.getNameIndex()=91 | lv.getName()=inst| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=1
    --------------------第 2 個局部變量的信息
    lv.getStartPC()=10| lv.getLength=60| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=2
    --------------------第 3 個局部變量的信息
    lv.getStartPC()=17| lv.getLength=44| lv.getNameIndex()=70 | lv.getName()=startTime| lv.getSignatureIndex()=71 | lv.getSignature()=J |lv.getIndex()=3
    --------------------第 4 個局部變量的信息
    lv.getStartPC()=29| lv.getLength=32| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=5
    完整的code.toString的信息
    public static void main(String[] argv)
    Code(max_stack = 4, max_locals = 6, code_length = 71)
    0: new <StringBuilder> (1)
    3: dup
    4: invokespecial StringBuilder.<init> ()V (74)
    7: astore_1
    8: iconst_0
    9: istore_2
    10: goto #64
    13: invokestatic ToolUtil.printStart ()J (54)
    16: lstore_3
    17: aload_1
    18: aload_0
    19: iload_2
    20: aaload
    21: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (75)
    24: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (60)
    27: astore %5
    29: ldc "buildString" (62)
    31: lload_3
    32: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (63)
    35: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    38: new <java.lang.StringBuilder> (18)
    41: dup
    42: ldc "Constructed string of length " (81)
    44: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    47: aload %5
    49: invokevirtual java.lang.String.length ()I (83)
    52: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (86)
    55: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    58: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    61: iinc %2 1
    64: iload_2
    65: aload_0
    66: arraylength
    67: if_icmplt #13
    70: return

    Attribute(s) =
    LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 51), LineNumber(17, 52),
    LineNumber(29, 54), LineNumber(35, 56), LineNumber(47, 57), LineNumber(58, 56),
    LineNumber(61, 48), LineNumber(70, 59)
    LocalVariable(start_pc = 0, length = 71, index = 0:String[] argv)
    LocalVariable(start_pc = 8, length = 63, index = 1:StringBuilder inst)
    LocalVariable(start_pc = 10, length = 60, index = 2:int i)
    LocalVariable(start_pc = 17, length = 44, index = 3:long startTime)
    LocalVariable(start_pc = 29, length = 32, index = 5:String result)

    end method method method-----------------------------------


      回復  更多評論
      
    # re: 用 BCEL 設計字節碼(三)直接在方法的調用處添加方法 2009-08-16 18:46 | Frank_Fang
    自己生成的字節碼,注意看與上一個main中的區別
    因為main中調用buildString(Integer.parseInt(argv[i]))時,方法的參數是使用語句產生的,而我在自己生成字節碼時,是在buildString的invokevirtual的上兩個指令加的我自己的指令,與編譯器產生的有的區別

    完整的code.toString的信息
    public String buildString(int length)
    Code(max_stack = 3, max_locals = 4, code_length = 51)
    0: ldc "" (16)
    2: astore_2
    3: iconst_0
    4: istore_3
    5: goto #37
    8: new <java.lang.StringBuilder> (18)
    11: dup
    12: aload_2
    13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
    16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    19: iload_3
    20: bipush 26
    22: irem
    23: bipush 97
    25: iadd
    26: i2c
    27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
    30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    33: astore_2
    34: iinc %3 1
    37: iload_3
    38: iload_1
    39: if_icmplt #8
    42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    45: aload_2
    46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    49: aload_2
    50: areturn

    Attribute(s) =
    LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
    LineNumber(42, 13), LineNumber(49, 15)
    LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
    LocalVariable(start_pc = 0, length = 51, index = 1:int length)
    LocalVariable(start_pc = 3, length = 48, index = 2:String result)
    LocalVariable(start_pc = 5, length = 37, index = 3:int i)

    end method method method-----------------------------------


    完整的code.toString的信息
    private String testInvokeMethod()
    Code(max_stack = 3, max_locals = 4, code_length = 29)
    0: aconst_null
    1: astore_1
    2: invokestatic ToolUtil.printStart ()J (86)
    5: lstore_2
    6: aload_0
    7: bipush 10
    9: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
    12: astore_1
    13: ldc "buildString" (87)
    15: lload_2
    16: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (91)
    19: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    22: ldc "我是測試方法,我是測試方法,我是測試方法,我是測試方法" (56)
    24: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    27: aload_1
    28: areturn

    Attribute(s) =
    LocalVariable(start_pc = 0, length = 29, index = 0:StringBuilder this)
    LocalVariable(start_pc = 6, length = 23, index = 1:String temp)
    LocalVariable(start_pc = 0, length = 29, index = 2:long starttime)
    LineNumber(0, 27), LineNumber(6, 31), LineNumber(19, 35), LineNumber(27, 37)


    end method method method-----------------------------------



    完整的code.toString的信息
    public static void main(String[] argv)
    Code(max_stack = 5, max_locals = 6, code_length = 71)
    0: new <StringBuilder> (1)
    3: dup
    4: invokespecial StringBuilder.<init> ()V (61)
    7: astore_1
    8: iconst_0
    9: istore_2
    10: goto #64
    13: aload_1
    14: aload_0
    15: iload_2
    16: invokestatic ToolUtil.printStart ()J (86)
    19: lstore %4
    21: aaload
    22: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (62)
    25: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
    28: astore_3
    29: ldc "buildString" (87)
    31: lload %4
    33: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (91)
    36: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    39: new <java.lang.StringBuilder> (18)
    42: dup
    43: ldc "Constructed string of length " (68)
    45: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    48: aload_3
    49: invokevirtual java.lang.String.length ()I (70)
    52: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (73)
    55: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    58: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    61: iinc %2 1
    64: iload_2
    65: aload_0
    66: arraylength
    67: if_icmplt #13
    70: return

    Attribute(s) =
    LocalVariable(start_pc = 0, length = 71, index = 0:String[] argv)
    LocalVariable(start_pc = 8, length = 63, index = 1:StringBuilder inst)
    LocalVariable(start_pc = 10, length = 61, index = 2:int i)
    LocalVariable(start_pc = 36, length = 28, index = 3:String result)
    LocalVariable(start_pc = 0, length = 71, index = 4:long starttime)
    LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 52), LineNumber(36, 56),
    LineNumber(48, 57), LineNumber(58, 56), LineNumber(61, 48), LineNumber(70, 59)


    end method method method-----------------------------------


      回復  更多評論
      
    主站蜘蛛池模板: 亚洲午夜日韩高清一区| 亚洲AV无码一区二区一二区| 免费jjzz在在线播放国产| 免费观看91视频| 精品久久久久久无码免费 | 91精品全国免费观看含羞草| 一级女性全黄久久生活片免费 | 999任你躁在线精品免费不卡| 日本高清不卡中文字幕免费| 亚洲精品无码av中文字幕| 亚洲福利电影一区二区?| 亚洲精品无码乱码成人| 亚洲精品成人在线| 日本xxwwxxww在线视频免费| 日本高清在线免费| 99在线观看免费视频| 免费av片在线观看网站| 日韩精品无码免费专区午夜| 四虎精品免费永久免费视频| www亚洲精品久久久乳| 亚洲中文精品久久久久久不卡| 亚洲精品91在线| 亚洲欧洲精品久久| 亚洲黄色中文字幕| 亚洲国产精品免费视频| 亚洲狠狠综合久久| 亚洲国产高清在线| 婷婷精品国产亚洲AV麻豆不片 | 日韩毛片免费一二三| 亚洲AV无码一区二区三区电影| 亚洲第一成年网站视频| 亚洲AV综合永久无码精品天堂| 亚洲中文字幕精品久久| 亚洲午夜无码久久久久软件| 亚洲欧美日韩国产精品一区| 亚洲一区AV无码少妇电影| 亚洲精品美女久久7777777 | 免费一级毛片正在播放| 免费一看一级毛片人| 亚洲色偷偷狠狠综合网| 国产自偷亚洲精品页65页|