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

          前一個是直接生成了一個一個方法對原方法進行調用,現在直接在原方法上進行修改
          即將


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

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

                  System.out.println(result);

                  
          return result;
              }

              
              
              
          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
          {
              
          private String buildString(int length) {
                  
                  System.out.println("start start start");
                  long starttime = System.currentTimeMillis();

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

                  System.out.println(result);
                  
                  System.out.println("Call to buildString$impl took " +
                          (System.currentTimeMillis()-starttime) + " ms.");
                  System.out.println("end end end end");

                  
                  
          return result;
              }

              
              
              
          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());
                  }

              }

          }



          修改代碼如下:

          import java.io.FileOutputStream;
          import java.util.Iterator;

          import org.apache.bcel.Constants;
          import org.apache.bcel.classfile.ClassParser;
          import org.apache.bcel.classfile.JavaClass;
          import org.apache.bcel.classfile.LineNumberTable;
          import org.apache.bcel.classfile.LocalVariableTable;
          import org.apache.bcel.classfile.Method;
          import org.apache.bcel.generic.ClassGen;
          import org.apache.bcel.generic.ConstantPoolGen;
          import org.apache.bcel.generic.InstructionConstants;
          import org.apache.bcel.generic.InstructionFactory;
          import org.apache.bcel.generic.InstructionHandle;
          import org.apache.bcel.generic.InstructionList;
          import org.apache.bcel.generic.InvokeInstruction;
          import org.apache.bcel.generic.LocalVariableGen;
          import org.apache.bcel.generic.MethodGen;
          import org.apache.bcel.generic.ObjectType;
          import org.apache.bcel.generic.PUSH;
          import org.apache.bcel.generic.Type;


          public class BCELTiming2 {
              
              
          private static void modifyWrapper(ClassGen cgen,Method method){
                  
                  InstructionFactory ifact 
          = new InstructionFactory(cgen);
                  ConstantPoolGen pgen 
          = cgen.getConstantPool();
                  
                  String cname 
          = cgen.getClassName();
                  
                  MethodGen wrapgen 
          = new MethodGen(method,cname,pgen);
                  
                  
          //除掉這個原來的方法
                  cgen.removeMethod(method);
                  
                  
                  System.out.println(
          "打印出這個方法看看---------------------------------start");
                  System.out.println(wrapgen.toString());
                  System.out.println(
          "打印出這個方法看看---------------------------------end");
                  
                  
                  
                  InstructionList ilist 
          = wrapgen.getInstructionList();
                  System.out.println(
          "看看這個方法的InstructionList-----------------------------start");
                  System.out.println(ilist.toString());
                  System.out.println(
          "看看這個方法的InstructionList-----------------------------start");
                  
                  System.out.println(
          "看看這個方法InstructionList的各個InstructionHandle的信息--------------------start");
                  Iterator handleIt 
          = ilist.iterator();
                  
                  
          while(handleIt.hasNext()){
                      InstructionHandle iHandle 
          = (InstructionHandle)handleIt.next();
                      System.out.println(iHandle.getAttributes());
                      System.out.println(iHandle.toString());
                  }

                  
                  System.out.println(
          "看看這個方法InstructionList的各個InstructionHandle的信息--------------------end");
                  
                  System.out.println(
          "先看看此方法的LocalVariableTable的信息--------------------------------------start");
                  LocalVariableTable lvt 
          = wrapgen.getLocalVariableTable(pgen);
                  System.out.println(lvt.toString());
                  System.out.println(
          "先看看此方法的LocalVariableTable的信息--------------------------------------end");
                  
                  LineNumberTable lnt 
          = wrapgen.getLineNumberTable(pgen);
                  System.out.println(
          "LineNumberTable--------------------------------------start");
                  System.out.println(lnt.toString());
                  System.out.println(
          "LineNumberTable--------------------------------------end");
                  
                  
                  Type returnType 
          = wrapgen.getReturnType();
                  
                  Type[] types 
          = wrapgen.getArgumentTypes();
                  
          int slot = wrapgen.isStatic()?0:1;//非靜態方法slot 0處應該存儲的是this
                  //// 這種方式與Java如何處理方法調用有關。對于非靜態的方法,每次調用的第一個(隱藏的)參數是目標對象的this引用(就是位置0儲存的內容)。
                  for(int i = 0;i<types.length;i++){
                      slot 
          += types[i].getSize();//long,double的size為2
                  }

                  
                  
          /*
                   * 判斷原來的方法用到了哪些局部變量,獲得局部變量中已經用到的最大索引
                   * 將新產生的局部變量加到最大索引后,本來準備自己寫的
                   * BCEL中已經這樣的方法了
                   
          */

                  
                  LocalVariableGen lvg 
          = wrapgen.addLocalVariable("starttime", Type.LONG, nullnull);
                  
                  
                  
          //先插入一條打印語句不使用局部變量
                  InstructionList printlnList = ifact.createPrintln("start test start test start test start test");
                  
                  InvokeInstruction invokestatic 
          = ifact.createInvoke("java.lang.System"
                          
          "currentTimeMillis", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC);
                  
                  
                  InstructionHandle firstHandle 
          = printlnList.append(invokestatic);
                  
          //這個會不會將局部變量為2的地方的局部變量給覆蓋,然后此局部變量也沒有定義名字??slot這個index怎么來確定
                  
          //slot現在應該為2,之前代碼塊放的是result信息是aload,
                  
          //寫到新產生的局部變量的索引處
                  printlnList.append(InstructionFactory.createStore(Type.LONG, lvg.getIndex()));
                  
                  
          //加入到之前的inlist中
                  ilist.insert(printlnList);
                  
                  
          //
                  
                  
          //在語句最后在打印結束語句,不能簡單插入在最后面,加入方法有返回值,則要插入在return 之前
                  
          //在return的時候,還要先將return的引用加入到操作數棧,怎么獲取result在局部變量中index
                  InstructionHandle insertposition =null;
                  
          if(returnType.getType()!=Type.VOID.getType()){
                      insertposition = ilist.getEnd().getPrev();

                      
                  }
          else{
                      
          //返回值為Type.void的話,由于沒有返回值,因此只需要在return指令前加就夠了,往前取一個即可
                      insertposition = ilist.getEnd();
                  }

                  InstructionList tempList 
          = new InstructionList();
                  tempList.append(ifact.createFieldAccess(
          "java.lang.System"
                          , 
          "out"new ObjectType("java.io.PrintStream"), 
                          Constants.GETSTATIC));
                  
                  tempList.append(InstructionFactory.DUP);
                  tempList.append(InstructionFactory.DUP);
                  
                  String text 
          = "Call to method "+wrapgen.getName()+" took ";
                  tempList.append(
          new PUSH(pgen,text));
                  tempList.append(ifact.createInvoke(
          "java.io.PrintStream"
                          
          "print", Type.VOID, new Type[]{Type.STRING}
                          Constants.INVOKEVIRTUAL));
                  tempList.append(ifact.createInvoke(
          "java.lang.System"
                          
          "currentTimeMillis", Type.LONG, Type.NO_ARGS, 
                          Constants.INVOKESTATIC));
                  
          //獲取之前的的starttime局部變量
                  tempList.append(InstructionFactory.createLoad(Type.LONG, lvg.getIndex()));
                  tempList.append(InstructionConstants.LSUB);
                  tempList.append(ifact.createInvoke(
          "java.io.PrintStream"
                          
          "print", Type.VOID, new Type[]{Type.LONG}
                          Constants.INVOKEVIRTUAL));
                  tempList.append(
          new PUSH(pgen," ms."));
                  tempList.append(ifact.createInvoke(
          "java.io.PrintStream"
                          
          "println", Type.VOID, new Type[]{Type.STRING}
                          Constants.INVOKEVIRTUAL));
                  
                  
          //在return之前的最后一句是打印end end end.信息
                  tempList.append(ifact.createPrintln("end end end end end end end end end end"));
                  
                  ilist.insert(insertposition,tempList);
                  
                  
                  
                  
                  
                  
                  
          //        LocalVariableGen lvgen  = new LocalVariableGen(slot,"start",Type.LONG,null,null);
                  
                  
          //finalize the construted method
                  wrapgen.stripAttributes(false);
                  wrapgen.setMaxStack();
                  wrapgen.setMaxLocals();

                  cgen.addMethod(wrapgen.getMethod());
                  
                  System.out.println();
                  System.out.println();
                  System.out.println(wrapgen.getInstructionList());
                  ilist.dispose();
                  
              }

              
              
              
              
              
              
          public static void main(String[] args) {
                  
                  args[
          0]="D:\\java to eclipse\\javaeclipsestudy\\workspace\\BCELTest\\bin\\StringBuilder.class";
                  args[
          1]="buildString";
                  String targetClassfile 
          = "StringBuilder.class";
                  
          if(args.length==2 && args[0].endsWith(".class")){
                      
          try{
                          JavaClass jclas 
          = new ClassParser(args[0]).parse();
                          
                          ClassGen cgen 
          = new ClassGen(jclas);
                          Method[] methods 
          = jclas.getMethods();
                          
                          
          int index;
                          
          for(index =0;index<methods.length;index++){
                              
          if(methods[index].getName().equals(args[1])){
                                  
          break;
                              }

                          }

                          
          if(index<methods.length){
                              modifyWrapper(cgen,methods[index]);
                              FileOutputStream fos 
          = new FileOutputStream(targetClassfile);
                              cgen.getJavaClass().dump(fos);
                              fos.close();
                          }
          else{
                              System.err.println(
          "Method " + args[1]+"not found in"+ args[0]);
                          }

                      }
          catch(Exception e){
                          e.printStackTrace();
                      }

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


              }



          }

          posted on 2009-08-13 22:53 Frank_Fang 閱讀(1987) 評論(2)  編輯  收藏 所屬分類: bcel javassist

          評論:
          # re: 用 BCEL 設計字節碼(二)直接在原方法上加指令 2009-08-15 20:59 | 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]("")
          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]("main")
          54:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
          55:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
          56:CONSTANT_Methodref[10](class_index = 57, name_and_type_index = 59)
          57:CONSTANT_Class[7](name_index = 58)
          58:CONSTANT_Utf8[1]("java/lang/Integer")
          59:CONSTANT_NameAndType[12](name_index = 60, signature_index = 61)
          60:CONSTANT_Utf8[1]("parseInt")
          61:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
          62:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 63)
          63:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
          64:CONSTANT_String[8](string_index = 65)
          65:CONSTANT_Utf8[1]("Constructed string of length ")
          66:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 67)
          67:CONSTANT_NameAndType[12](name_index = 48, signature_index = 68)
          68:CONSTANT_Utf8[1]("()I")
          69:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 70)
          70:CONSTANT_NameAndType[12](name_index = 31, signature_index = 71)
          71:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
          72:CONSTANT_Utf8[1]("argv")
          73:CONSTANT_Utf8[1]("[Ljava/lang/String;")
          74:CONSTANT_Utf8[1]("inst")
          75:CONSTANT_Utf8[1]("SourceFile")
          76:CONSTANT_Utf8[1]("StringBuilder.java")
          --------------------------域----------------------------
          -----------域的長度,此類定義的成員變量的個數-------------0




          start method method method-----------------------------------
          方法訪問標志
          1
          方法訪問名稱

          CONSTANT_Utf8[1]("")
          方法簽名
          ()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@10b4199
          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 ()
          Code(max_stack = 1, max_locals = 1, code_length = 5)
          0: aload_0
          1: invokespecial java.lang.Object. ()V (8)
          4: return

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

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


          start method method method-----------------------------------
          方法訪問標志
          2
          方法訪問名稱
          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@1ffbd68
          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的信息
          private 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 (18)
          11: dup
          12: aload_2
          13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
          16: invokespecial java.lang.StringBuilder. (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, 6), LineNumber(3, 7), LineNumber(8, 8), LineNumber(34, 7),
          LineNumber(42, 10), LineNumber(49, 12)
          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-----------------------------------
          方法訪問標志
          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()=72 | lv.getName()=argv| lv.getSignatureIndex()=73 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
          --------------------第 1 個局部變量的信息
          lv.getStartPC()=8| lv.getLength=51| lv.getNameIndex()=74 | 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 (1)
          3: dup
          4: invokespecial StringBuilder. ()V (55)
          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 (56)
          20: invokespecial StringBuilder.buildString (I)Ljava/lang/String; (62)
          23: astore_3
          24: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
          27: new (18)
          30: dup
          31: ldc "Constructed string of length " (64)
          33: invokespecial java.lang.StringBuilder. (Ljava/lang/String;)V (26)
          36: aload_3
          37: invokevirtual java.lang.String.length ()I (66)
          40: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (69)
          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, 17), LineNumber(8, 18), LineNumber(13, 19), LineNumber(24, 20),
          LineNumber(36, 21), LineNumber(46, 20), LineNumber(49, 18), LineNumber(58, 23)

          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-15 21:08 | 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]("main")
          54:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
          55:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
          56:CONSTANT_Methodref[10](class_index = 57, name_and_type_index = 59)
          57:CONSTANT_Class[7](name_index = 58)
          58:CONSTANT_Utf8[1]("java/lang/Integer")
          59:CONSTANT_NameAndType[12](name_index = 60, signature_index = 61)
          60:CONSTANT_Utf8[1]("parseInt")
          61:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
          62:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 63)
          63:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
          64:CONSTANT_String[8](string_index = 65)
          65:CONSTANT_Utf8[1]("Constructed string of length ")
          66:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 67)
          67:CONSTANT_NameAndType[12](name_index = 48, signature_index = 68)
          68:CONSTANT_Utf8[1]("()I")
          69:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 70)
          70:CONSTANT_NameAndType[12](name_index = 31, signature_index = 71)
          71:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
          72:CONSTANT_Utf8[1]("argv")
          73:CONSTANT_Utf8[1]("[Ljava/lang/String;")
          74:CONSTANT_Utf8[1]("inst")
          75:CONSTANT_Utf8[1]("SourceFile")
          76:CONSTANT_Utf8[1]("StringBuilder.java")
          77:CONSTANT_Utf8[1]("start test start test start test start test")
          78:CONSTANT_String[8](string_index = 77)
          79:CONSTANT_Utf8[1]("currentTimeMillis")
          80:CONSTANT_Utf8[1]("()J")
          81:CONSTANT_NameAndType[12](name_index = 79, signature_index = 80)
          82:CONSTANT_Methodref[10](class_index = 38, name_and_type_index = 81)
          83:CONSTANT_Utf8[1]("Call to method buildString took ")
          84:CONSTANT_String[8](string_index = 83)
          85:CONSTANT_Utf8[1]("print")
          86:CONSTANT_NameAndType[12](name_index = 85, signature_index = 28)
          87:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 86)
          88:CONSTANT_Utf8[1]("(J)V")
          89:CONSTANT_NameAndType[12](name_index = 85, signature_index = 88)
          90:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 89)
          91:CONSTANT_Utf8[1](" ms.")
          92:CONSTANT_String[8](string_index = 91)
          93:CONSTANT_Utf8[1]("end end end end end end end end end end")
          94:CONSTANT_String[8](string_index = 93)
          95:CONSTANT_Utf8[1]("starttime")
          96:CONSTANT_Utf8[1]("J")
          --------------------------域----------------------------
          -----------域的長度,此類定義的成員變量的個數-------------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@1ffb8dc
          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, 2)
          LocalVariable(start_pc = 0, length = 5, index = 0:StringBuilder this)

          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()=72 | lv.getName()=argv| lv.getSignatureIndex()=73 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
          --------------------第 1 個局部變量的信息
          lv.getStartPC()=8| lv.getLength=51| lv.getNameIndex()=74 | 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 (55)
          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 (56)
          20: invokespecial StringBuilder.buildString (I)Ljava/lang/String; (62)
          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 " (64)
          33: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
          36: aload_3
          37: invokevirtual java.lang.String.length ()I (66)
          40: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (69)
          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, 17), LineNumber(8, 18), LineNumber(13, 19), LineNumber(24, 20),
          LineNumber(36, 21), LineNumber(46, 20), LineNumber(49, 18), LineNumber(58, 23)

          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-----------------------------------


          start method method method-----------------------------------
          方法訪問標志
          2
          方法訪問名稱
          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 的長度 198
          code.getCode().length 屬性結構中的code數組的長度 code_length 的長度 96
          給出該方法在執行中任何點操作數棧上字的最大個數 6
          給出該方法使用的局部變量的個數,包括調用時傳遞給方法的參數 6
          code的字節信息調用code.getCode()返回byte[] [B@1c29ab2
          ce.length===========0
          code 內部結構中的各異常信息結構------------方法內部的try 塊catch的信息----------
          方法的Code的LineNumberTable
          方法的Code的LocalVariableTable
          LocalVariableTable
          localvariableTable==null false
          lvs==null false
          lvs.length======5
          --------------------第 0 個局部變量的信息
          lv.getStartPC()=13| lv.getLength=83| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
          --------------------第 1 個局部變量的信息
          lv.getStartPC()=13| lv.getLength=83| lv.getNameIndex()=48 | lv.getName()=length| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=1
          --------------------第 2 個局部變量的信息
          lv.getStartPC()=16| lv.getLength=80| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=2
          --------------------第 3 個局部變量的信息
          lv.getStartPC()=18| lv.getLength=40| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=3
          --------------------第 4 個局部變量的信息
          lv.getStartPC()=0| lv.getLength=96| lv.getNameIndex()=95 | lv.getName()=starttime| lv.getSignatureIndex()=96 | lv.getSignature()=J |lv.getIndex()=4
          完整的code.toString的信息
          private String buildString(int length)
          Code(max_stack = 6, max_locals = 6, code_length = 96)
          0: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
          3: ldc "start test start test start test start test" (78)
          5: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
          8: invokestatic java.lang.System.currentTimeMillis ()J (82)
          11: lstore %4
          13: ldc "" (16)
          15: astore_2
          16: iconst_0
          17: istore_3
          18: goto #50
          21: new <java.lang.StringBuilder> (18)
          24: dup
          25: aload_2
          26: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
          29: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
          32: iload_3
          33: bipush 26
          35: irem
          36: bipush 97
          38: iadd
          39: i2c
          40: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
          43: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
          46: astore_2
          47: iinc %3 1
          50: iload_3
          51: iload_1
          52: if_icmplt #21
          55: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
          58: aload_2
          59: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
          62: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
          65: dup
          66: dup
          67: ldc "Call to method buildString took " (84)
          69: invokevirtual java.io.PrintStream.print (Ljava/lang/String;)V (87)
          72: invokestatic java.lang.System.currentTimeMillis ()J (82)
          75: lload %4
          77: lsub
          78: invokevirtual java.io.PrintStream.print (J)V (90)
          81: ldc " ms." (92)
          83: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
          86: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
          89: ldc "end end end end end end end end end end" (94)
          91: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
          94: aload_2
          95: areturn

          Attribute(s) =
          LocalVariable(start_pc = 13, length = 83, index = 0:StringBuilder this)
          LocalVariable(start_pc = 13, length = 83, index = 1:int length)
          LocalVariable(start_pc = 16, length = 80, index = 2:String result)
          LocalVariable(start_pc = 18, length = 40, index = 3:int i)
          LocalVariable(start_pc = 0, length = 96, index = 4:long starttime)
          LineNumber(13, 6), LineNumber(16, 7), LineNumber(21, 8), LineNumber(47, 7),
          LineNumber(55, 10), LineNumber(94, 12)

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


          可以看出局部變量this 的start_pc顯然是不正確的
            回復  更多評論
            
          主站蜘蛛池模板: 陕西省| 萨嘎县| 浑源县| 右玉县| 资中县| 镇远县| 普格县| 吉木萨尔县| 道真| 称多县| 泸溪县| 修武县| 禹州市| 尚义县| 什邡市| 馆陶县| 香港| 沙雅县| 施秉县| 福州市| 唐海县| 桦川县| 剑川县| 鄂托克旗| 于都县| 特克斯县| 沧州市| 平潭县| 汝州市| 南岸区| 安康市| 水富县| 武定县| 会理县| 苍山县| 辽中县| 印江| 自治县| 绥棱县| 桐梓县| 卢湾区|