隨筆-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 閱讀(1732) 評論(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-----------------------------------


            回復  更多評論
            
          <2009年8月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          常用鏈接

          留言簿(1)

          隨筆分類(204)

          隨筆檔案(100)

          收藏夾(8)

          牛人博客鏈接

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 开封县| 武乡县| 合肥市| 隆安县| 兴义市| 宿迁市| 罗江县| 昂仁县| 双流县| 五指山市| 宁波市| 五大连池市| 手游| 云林县| 阿城市| 明光市| 东台市| 疏勒县| 麦盖提县| 赞皇县| 冷水江市| 通榆县| 神木县| 永城市| 清苑县| 荔波县| 长垣县| 棋牌| 台山市| 维西| 江都市| 拉萨市| 海城市| 巴南区| 六枝特区| 湾仔区| 朝阳市| 扎鲁特旗| 保康县| 牟定县| 和田县|