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

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

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

    隨筆-204  評論-149  文章-0  trackbacks-0
    查到一篇使用BCEL了,Java 編程的動態(tài)性,第 7 部分: 用 BCEL 設(shè)計字節(jié)碼,網(wǎng)址是http://www-128.ibm.com/developerworks/cn/java/j-dyn0414/

    字節(jié)碼處理的工具也挺多,什么時候再看看asm
    import java.io.FileOutputStream;

    import org.apache.bcel.Constants;
    import org.apache.bcel.classfile.ClassParser;
    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.GETSTATIC;
    import org.apache.bcel.generic.INVOKEVIRTUAL;
    import org.apache.bcel.generic.InstructionConstants;
    import org.apache.bcel.generic.InstructionFactory;
    import org.apache.bcel.generic.InstructionList;
    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 BCELTiming {
        
        
        
    private static void addWrapper(ClassGen cgen,Method method){
            
    //set up the construction tools
            InstructionFactory ifact = new InstructionFactory(cgen);
            InstructionList ilist 
    = new InstructionList();
            ConstantPoolGen pgen 
    = cgen.getConstantPool();
            String cname 
    = cgen.getClassName();
            MethodGen wrapgen 
    = new MethodGen(method,cname,pgen);
            wrapgen.setInstructionList(ilist);
            
            
    //rename a copy of the original method
            MethodGen methgen = new MethodGen(method,cname,pgen);
            cgen.removeMethod(method);
            String iname 
    = methgen.getName()+"$impl";
            methgen.setName(iname);
            cgen.addMethod(methgen.getMethod());
            Type returnType 
    = methgen.getReturnType();
            
    //        methgen.addLocalVariable(name, type, slot, start, end)
            
            Type[] types 
    = methgen.getArgumentTypes();
            
    int slot = methgen.isStatic()?0:1;//非靜態(tài)方法slot 0處應(yīng)該存儲的是this
            //// 這種方式與Java如何處理方法調(diào)用有關(guān)。對于非靜態(tài)的方法,每次調(diào)用的第一個(隱藏的)參數(shù)是目標(biāo)對象的this引用(就是位置0儲存的內(nèi)容)。
            for(int i = 0;i<types.length;i++){
                slot 
    += types[i].getSize();//long,double的size為2
            }

            
            
    //save time prior to invocation
            
    //createInvoke在常量池增加了 addMethodref,并且addMethodref方法會先在常量池中查找是否有這個方法存在,沒有則創(chuàng)建一系列的與此方法相關(guān)的常量池內(nèi)容
            
    //看看這個方法是怎么實現(xiàn)的,為什么此方法中INVOKEINTERFACE的要有nargs
            
    //InstructionFactory的實例方法一般要用到cp在常量池中添加引用,其靜態(tài)的方法一般只是創(chuàng)建一些指令,而這些指令不需要在常量池添加內(nèi)容
            
    //INVOKEXXXXX指令包括一個index指示此方法在常量池中的索引
            //// 調(diào)用靜態(tài)的long java.lang.System.currentTimeMillis()方法,調(diào)用結(jié)束后函數(shù)的返回的long類型的值會壓入operand stack操作數(shù)堆棧
            ilist.append(ifact.createInvoke("java.lang.System""currentTimeMillis"
                    Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
    //currentTimemillis()的方法結(jié)果在operand stack棧頂
            
            
    //createStore方法生成了XSTORE指令,彈出operand stack棧頂?shù)脑貙懭氲侥硞€局部變量中,
            
    //參照之前打印出的局部變量的信息可以知道若是實例方法則 index=0處保留的this,之后是用到的方法參數(shù)的index,然后是方法內(nèi)定義的局部變量
            
    //slot標(biāo)記在局部變量中的位置,
            
    //這個局部變量沒有設(shè)置名稱????????
            ilist.append(InstructionFactory.createStore(Type.LONG, slot));
            
            
    //call the wrapped method
            int offset =0;
            
    short invoke = Constants.INVOKESTATIC;
            
    //如果是實例方法則load this到棧中
            if(!methgen.isStatic()){
                
    //// 如果不是調(diào)用靜態(tài)函數(shù),將調(diào)用的第一個(隱藏的)參數(shù)(目標(biāo)對象的this引用)壓入operand stack
                ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0));
                offset 
    =1;
                invoke 
    = Constants.INVOKESPECIAL;
            }

            
    //load 參數(shù)到棧中
            for(int i=0;i<types.length;i++){
                Type type 
    = types[i];
                ilist.append(InstructionFactory.createLoad(type, offset));
    // 按參數(shù)類型把參數(shù)一個個從本地變量堆棧取出,壓入operand stack
                
    //Long Double的size為2,void為0,其他的為1
                offset += type.getSize();
            }

            
            
    //執(zhí)行方法buildString$impl()
            ilist.append(ifact.createInvoke(cname, iname, 
                    returnType, types, invoke));
    //消耗oprand stack的this參數(shù)和length參數(shù)
                                                
    //并將結(jié)果保存在操作數(shù)的棧頂
            
            
    //stor result for return later
            if(returnType != Type.VOID){
                
    //+2是因為之前加的的long局部變量占兩個2個字,這個字是虛擬機(jī)定義的,一般為32位
                //// 將名為iname的函數(shù)返回值復(fù)制到本地變量堆棧的slot+2的位置上
                ilist.append(InstructionFactory.createStore(returnType,slot+2));
            }

            
            
    //print time required for method call
            
    //createFieldAccess中的 addFieldref方法先在ConstantFieldref常量池中根據(jù)type的描述符創(chuàng)建引用
            
    //然后根據(jù)kind來創(chuàng)建是GETFIELD,PUTFIELD,GETSTATIC,PUTSTATIC哪個指令
            //// 獲取靜態(tài)對象java.lang.System.out的引用,返回值壓入operand stack
            ilist.append(ifact.createFieldAccess("java.lang.System"
                    , 
    "out"new ObjectType("java.io.PrintStream"), 
                    Constants.GETSTATIC));
    //out會在棧頂
            
            
    //ilist.append(InstructionFactory.createDup(1));
            ilist.append(InstructionConstants.DUP);//復(fù)制棧頂元素out
            ilist.append(InstructionConstants.DUP);//在復(fù)制,當(dāng)前棧頂前三元素都為out引用,供下面的三次print使用out引用
            
            String text 
    = "Call to method "+methgen.getName()+" took ";
            
    //實際還是調(diào)的new LDC
            ilist.append(new PUSH(pgen,text));
            
            ilist.append(ifact.createInvoke(
    "java.io.PrintStream"
                    
    "print", Type.VOID, new Type[]{Type.STRING}
                    Constants.INVOKEVIRTUAL));
    //消耗調(diào)一個out和棧頂?shù)囊粋€元素
                                             
    // 調(diào)用結(jié)束,operand stack彈出一個String的引用和一個out的引用(還剩2個out),函數(shù)沒有返回值
            
            ilist.append(ifact.createInvoke(
    "java.lang.System"
                    
    "currentTimeMillis", Type.LONG, Type.NO_ARGS, 
                    Constants.INVOKESTATIC));
    //operand stack棧頂保留此方法的結(jié)果,即結(jié)束時間
                                             
    //調(diào)用java.lang.System.currentTimeMillis()方法,調(diào)用結(jié)束后函數(shù)的返回的long類型的值會壓入堆棧operand 
            
            
    //load 局部變量到棧頂
            
    //從本地變量堆棧的slot位置載入先前儲存的long值,壓入operand stack
            ilist.append(InstructionFactory.createLoad(Type.LONG, slot));
            
            
    //棧頂兩個元素進(jìn)行減法操作,結(jié)果保存在棧頂
            
    // 調(diào)用long的減法指令,彈出2個long值,并把結(jié)果壓入operand stack,現(xiàn)在operand stack的top第一個是long,第二個是out的引用
            ilist.append(InstructionConstants.LSUB);
            
            ilist.append(ifact.createInvoke(
    "java.io.PrintStream"
                    
    "print", Type.VOID, new Type[]{Type.LONG}
                    Constants.INVOKEVIRTUAL));
    //消耗一個out,和減法的結(jié)果
            
            
    // 將String對象" ms."放入pgen,并把其在pgen的引用(這個引用其實是字符串在常量池中的索引下標(biāo))壓入operand stack(供out.print(Sting)調(diào)用的參數(shù))
            ilist.append(new PUSH(pgen," ms."));//常量入棧,首先會判斷常量池中是否有此字符串
            ilist.append(ifact.createInvoke("java.io.PrintStream"
                    
    "println", Type.VOID, new Type[]{Type.STRING}
                    Constants.INVOKEVIRTUAL));
    //消耗調(diào)最后一個out和剛?cè)霔5? ms."
            
            
    //如果返回類型不為void,則將返回結(jié)果入棧并返回
            if(returnType != Type.VOID){
                
    //處理返回值,如果不為空,從本地局部對象堆棧的slot+2位置讀取指定類型的返回值壓入operand stack
                ilist.append(InstructionFactory.createLoad(returnType, slot+2));
            }

            
            ilist.append(InstructionFactory.createReturn(returnType));
    //根據(jù)相應(yīng)的返回類型創(chuàng)建相應(yīng)的返回指令
            
            
            
    //finalize the construted method
            wrapgen.stripAttributes(true);
            wrapgen.setMaxStack();
            wrapgen.setMaxLocals();
            cgen.addMethod(wrapgen.getMethod());
            ilist.dispose();
            
            
            
            
            
    /*
             * ifact.createPrintln(s)
             * 
             *     public InstructionList createPrintln( String s ) {
            InstructionList il = new InstructionList();
            int out = cp.addFieldref("java.lang.System", "out", "Ljava/io/PrintStream;");
            int println = cp.addMethodref("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
            il.append(new GETSTATIC(out));
            il.append(new PUSH(cp, s));
            il.append(new INVOKEVIRTUAL(println));
            return il;
        }
             
    */

            
            
        }


        
    /**
         * 
    @param args
         
    */

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


        }


    }




    public class StringBuilder
    {
        
    private String buildString$impl(int length) {
            String result 
    = "";
            
    for (int i = 0; i < length; i++{
                result 
    += (char)(i%26 + 'a');
            }

            
    return result;
        }

        
        
    private String buildString(int length) {
            
    long start = System.currentTimeMillis();
            String result 
    = buildString$impl(length);
            System.out.println(
    "Call to buildString$impl took " +
                (System.currentTimeMillis()
    -start) + " ms.");
            
    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());
            }

        }

    }



    字節(jié)碼
    --------------------------------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$impl")
    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_Utf8[1]("length")
    38:CONSTANT_Utf8[1]("I")
    39:CONSTANT_Utf8[1]("result")
    40:CONSTANT_Utf8[1]("Ljava/lang/String;")
    41:CONSTANT_Utf8[1]("i")
    42:CONSTANT_Utf8[1]("buildString")
    43:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 46)
    44:CONSTANT_Class[7](name_index = 45)
    45:CONSTANT_Utf8[1]("java/lang/System")
    46:CONSTANT_NameAndType[12](name_index = 47, signature_index = 48)
    47:CONSTANT_Utf8[1]("currentTimeMillis")
    48:CONSTANT_Utf8[1]("()J")
    49:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 50)
    50:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
    51:CONSTANT_Fieldref[9](class_index = 44, name_and_type_index = 52)
    **********************************************************************
    cc.toString : CONSTANT_Class[
    7](name_index = 45)
    java
    /lang/System
    cnat.toString : CONSTANT_NameAndType[
    12](name_index = 53, signature_index = 54)
    out
    Ljava
    /io/PrintStream;
    **********************************************************************
    52:CONSTANT_NameAndType[12](name_index = 53, signature_index = 54)
    53:CONSTANT_Utf8[1]("out")
    54:CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
    55:CONSTANT_String[8](string_index = 56)
    56:CONSTANT_Utf8[1]("Call to buildString$impl took ")
    57:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 58)
    58:CONSTANT_NameAndType[12](name_index = 31, signature_index = 59)
    59:CONSTANT_Utf8[1]("(J)Ljava/lang/StringBuilder;")
    60:CONSTANT_String[8](string_index = 61)
    61:CONSTANT_Utf8[1](" ms.")
    62:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 63)
    63:CONSTANT_NameAndType[12](name_index = 31, signature_index = 64)
    64:CONSTANT_Utf8[1]("(Ljava/lang/String;)Ljava/lang/StringBuilder;")
    65:CONSTANT_Methodref[10](class_index = 66, name_and_type_index = 68)
    66:CONSTANT_Class[7](name_index = 67)
    67:CONSTANT_Utf8[1]("java/io/PrintStream")
    68:CONSTANT_NameAndType[12](name_index = 69, signature_index = 28)
    69:CONSTANT_Utf8[1]("println")
    70:CONSTANT_Utf8[1]("start")
    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_Methodref[10](class_index = 1, name_and_type_index = 82)
    82:CONSTANT_NameAndType[12](name_index = 42, signature_index = 15)
    83:CONSTANT_String[8](string_index = 84)
    84:CONSTANT_Utf8[1]("Constructed string of length ")
    85:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 86)
    86:CONSTANT_NameAndType[12](name_index = 37, signature_index = 87)
    87:CONSTANT_Utf8[1]("()I")
    88:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 89)
    89:CONSTANT_NameAndType[12](name_index = 31, signature_index = 90)
    90:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
    91:CONSTANT_Utf8[1]("argv")
    92:CONSTANT_Utf8[1]("[Ljava/lang/String;")
    93:CONSTANT_Utf8[1]("inst")
    94:CONSTANT_Utf8[1]("SourceFile")
    95:CONSTANT_Utf8[1]("StringBuilder.java")
    ------------------------------------------------------
    ------------------------------------------------------
    start method method method
    -----------------------------------
    方法訪問標(biāo)志
    1
    方法訪問名稱
    me[i].getName()  
    <init>
    CONSTANT_Utf8[
    1]("<init>")
    方法簽名
    ()V
    CONSTANT_Utf8[
    1]("()V")
    方法的參數(shù)類型
    [Lorg.apache.bcel.generic.Type;@54172f
    方法的返回類型
    void
    方法的Code
    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(
    02)
    LocalVariable(start_pc 
    = 0, length = 5, index = 0:StringBuilder this)

    end method method method
    -----------------------------------
    start method method method
    -----------------------------------
    方法訪問標(biāo)志
    2
    方法訪問名稱
    me[i].getName()  buildString$impl
    CONSTANT_Utf8[
    1]("buildString$impl")
    方法簽名
    (I)Ljava
    /lang/String;
    CONSTANT_Utf8[
    1]("(I)Ljava/lang/String;")
    方法的參數(shù)類型
    [Lorg.apache.bcel.generic.Type;@1ed2ae8
    方法的返回類型
    java.lang.String
    方法的Code
    private String buildString$impl(int length)
    Code(max_stack 
    = 3, max_locals = 4, code_length = 44)
    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:   aload_2
    43:   areturn

    Attribute(s) 
    = 
    LineNumber(
    05), LineNumber(36), LineNumber(87), LineNumber(346), 
    LineNumber(
    429)
    LocalVariable(start_pc 
    = 0, length = 44, index = 0:StringBuilder this)
    LocalVariable(start_pc 
    = 0, length = 44, index = 1:int length)
    LocalVariable(start_pc 
    = 3, length = 41, index = 2:String result)
    LocalVariable(start_pc 
    = 5, length = 37, index = 3:int i)

    end method method method
    -----------------------------------
    start method method method
    -----------------------------------
    方法訪問標(biāo)志
    2
    方法訪問名稱
    me[i].getName()  buildString
    CONSTANT_Utf8[
    1]("buildString")
    方法簽名
    (I)Ljava
    /lang/String;
    CONSTANT_Utf8[
    1]("(I)Ljava/lang/String;")
    方法的參數(shù)類型
    [Lorg.apache.bcel.generic.Type;@19c26f5
    方法的返回類型
    java.lang.String
    方法的Code
    private String buildString(int length)
    Code(max_stack 
    = 6, max_locals = 5, code_length = 45)
    0:    invokestatic    java.lang.System.currentTimeMillis ()J (43)
    3:    lstore_2
    4:    aload_0
    5:    iload_1
    6:    invokespecial    StringBuilder.buildString$impl (I)Ljava/lang/String; (49)
    9:    astore        %4
    11:   getstatic        java.lang.System.out Ljava/io/PrintStream; (51)
    14:   new        <java.lang.StringBuilder> (18)
    17:   dup
    18:   ldc        "Call to buildString$impl took " (55)
    20:   invokespecial    java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    23:   invokestatic    java.lang.System.currentTimeMillis ()J (43)
    26:   lload_2
    27:   lsub
    28:   invokevirtual    java.lang.StringBuilder.append (J)Ljava/lang/StringBuilder; (57)
    31:   ldc        " ms." (60)
    33:   invokevirtual    java.lang.StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; (62)
    36:   invokevirtual    java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    39:   invokevirtual    java.io.PrintStream.println (Ljava/lang/String;)V (65)
    42:   aload        %4
    44:   areturn

    Attribute(s) 
    = 
    LineNumber(
    013), LineNumber(414), LineNumber(1115), LineNumber(2316), 
    LineNumber(
    3915), LineNumber(4217)
    LocalVariable(start_pc 
    = 0, length = 45, index = 0:StringBuilder this)
    LocalVariable(start_pc 
    = 0, length = 45, index = 1:int length)
    LocalVariable(start_pc 
    = 4, length = 41, index = 2:long start)
    LocalVariable(start_pc 
    = 11, length = 34, index = 4:String result)

    end method method method
    -----------------------------------
    start method method method
    -----------------------------------
    方法訪問標(biāo)志
    9
    方法訪問名稱
    me[i].getName()  main
    CONSTANT_Utf8[
    1]("main")
    方法簽名
    ([Ljava
    /lang/String;)V
    CONSTANT_Utf8[
    1]("([Ljava/lang/String;)V")
    方法的參數(shù)類型
    [Lorg.apache.bcel.generic.Type;@c1b531
    方法的返回類型
    void
    方法的Code
    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 (74)
    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 (75)
    20:   invokespecial    StringBuilder.buildString (I)Ljava/lang/String; (81)
    23:   astore_3
    24:   getstatic        java.lang.System.out Ljava/io/PrintStream; (51)
    27:   new        <java.lang.StringBuilder> (18)
    30:   dup
    31:   ldc        "Constructed string of length " (83)
    33:   invokespecial    java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
    36:   aload_3
    37:   invokevirtual    java.lang.String.length ()I (85)
    40:   invokevirtual    java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (88)
    43:   invokevirtual    java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
    46:   invokevirtual    java.io.PrintStream.println (Ljava/lang/String;)V (65)
    49:   iinc        %2    1
    52:   iload_2
    53:   aload_0
    54:   arraylength
    55:   if_icmplt        #13
    58:   return

    Attribute(s) 
    = 
    LineNumber(
    021), LineNumber(822), LineNumber(1323), LineNumber(2424), 
    LineNumber(
    3625), LineNumber(4624), LineNumber(4922), LineNumber(5827)

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

    posted on 2009-08-13 15:58 Frank_Fang 閱讀(1394) 評論(7)  編輯  收藏 所屬分類: bcel javassist

    評論:
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-13 16:13 | Frank_Fang
    Java虛擬機(jī)框架(frame)翻譯為幀是不是更貼切些
    用于存儲數(shù)據(jù)和部分結(jié)果,以及進(jìn)行動態(tài)鏈接,返回方法的值和調(diào)度異常
    每次Java方法被調(diào)用時創(chuàng)建一個新的frame,當(dāng)frame的方法結(jié)束時,不論正常的,還是不正常的結(jié)束(通過拋出一個異常)框架從創(chuàng)建該框架的線程的Java棧分配,每個frame有它自己的局部變量集,和自己的操作數(shù)棧,這些結(jié)構(gòu)的存儲器空間可以同時分配,因為局部變量區(qū)和操作數(shù)棧的大小是編譯期已知的。

    總的來說要把方法的局部變量集搞清楚,以及方法的操作數(shù)棧的當(dāng)前狀態(tài)搞清楚,以及每個jvm指令會對棧產(chǎn)生什么影響搞清楚。
    下一步在仔細(xì)研究一下修改class文件的其他東西。  回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-13 16:15 | Frank_Fang
    也可以看出String s = s+"ddd";時采用的是java.lang.StringBuilder來進(jìn)行操作的
    以及對于String s="abc" 與String s = new String("abc")這個字符串常量池就很清楚了  回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-13 18:43 | Frank_Fang
    public class AASTOREextends ArrayInstructionimplements StackConsumerAASTORE - Store into reference array

    Stack: ..., arrayref, index, value -> ...


    public class AALOADextends ArrayInstructionimplements StackProducerAALOAD - Load reference from array

    <red>Stack: ..., arrayref, index -> value</red>  回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-13 19:54 | Frank_Fang
    private String buildString(int)

    Attributes
    Code
    Byte
    offset Instruction Argument
    0 invokestatic System.currentTimeMillis ()J():long
    3 lstore_2
    4 aload_0
    5 iload_1
    6 invokespecial StringBuilder.buildString$impl (I)Ljava/lang/String;(int):String
    9 astore %4
    11 getstatic System.out Ljava/io/PrintStream;
    14 dup
    15 dup
    16 ldc "Call to method buildString$impl took "
    18 invokevirtual java.io.PrintStream.print (Ljava/lang/String;)V(String):void
    21 invokestatic System.currentTimeMillis ()J():long
    24 lload_2
    25 lsub
    26 invokevirtual java.io.PrintStream.print (J)V(long):void
    29 ldc " ms."
    31 invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V(String):void
    34 aload %4
    36 areturn


    實際生成的字節(jié)碼中沒有方法的Code屬性的LocalVariableTable
    LineNumberTable 信息
      回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼[未登錄] 2009-08-14 23:55 | alex
    實際生成的字節(jié)碼中沒有方法的Code屬性的LocalVariableTable
    LineNumberTable 信息 ???
    這個為什么沒有這些信息了?不知道你想過沒有???
      回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-15 00:17 | Frank_Fang
    @alex
    這個我現(xiàn)在還不太清楚
    wrapgen.stripAttributes(true);
    這個好像設(shè)置成false是生成lineNumber和Localvariabel Attribute的信息
    但是我設(shè)置成false之后,允許生成的代碼就報錯誤了
    Exception in thread "main" java.lang.ClassFormatError: Invalid length 44 in Loca
    lVariableTable in class file StringBuilder
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:12
    4)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    Could not find the main class: StringBuilder. Program will exit.


      回復(fù)  更多評論
      
    # re: 用 BCEL 設(shè)計字節(jié)碼 2009-08-15 19:58 | Frank_Fang
    @alex
    把stripAtrribute設(shè)置成false后,即新的方法生成linenumber和localvariable屬性

    這是原先的屬性信息
    private String buildString$impl(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) =
    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 = 40, index = 3:int i)
    LineNumber(0, 6), LineNumber(3, 7), LineNumber(8, 8), LineNumber(34, 7),
    LineNumber(42, 10), LineNumber(49, 12)


    --------------------------------------------------------
    完整的code.toString的信息
    private String buildString(int length)
    Code(max_stack = 6, max_locals = 5, code_length = 37)
    0: invokestatic java.lang.System.currentTimeMillis ()J (81)
    3: lstore_2
    4: aload_0
    5: iload_1
    6: invokespecial StringBuilder.buildString$impl (I)Ljava/lang/String; (83)
    9: astore %4
    11: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
    14: dup
    15: dup
    16: ldc "Call to method buildString$impl took " (85)
    18: invokevirtual java.io.PrintStream.print (Ljava/lang/String;)V (88)
    21: invokestatic java.lang.System.currentTimeMillis ()J (81)
    24: lload_2
    25: lsub
    26: invokevirtual java.io.PrintStream.print (J)V (91)
    29: ldc " ms." (93)
    31: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
    34: aload %4
    36: areturn

    Attribute(s) =
    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 = 40, index = 3:int i)
    LineNumber(0, 6), LineNumber(3, 7), LineNumber(8, 8), LineNumber(34, 7),
    LineNumber(42, 10), LineNumber(49, 12)

    end method method method-----------------------------------
    這個屬性信息使用還是使用的原先方法的,顯然length=55超過了指令的長度
    36,執(zhí)行時會檢查類的局部變量屬性信息發(fā)現(xiàn)不正確就報錯了

    這兩個屬性的信息應(yīng)該是用來調(diào)試器來使用的,可以自己在字節(jié)碼文件中自己添加這些信息,不過自己添加比較麻煩.
    不過我另外一個程序的方法也自己生成了屬性信息,這些屬性信息也改變了,但是改變的不正確,但是程序能夠執(zhí)行。。

    這中的原因我現(xiàn)在也搞不清楚了。

      回復(fù)  更多評論
      
    主站蜘蛛池模板: 色播在线永久免费视频| 免费在线看v网址| 亚洲中文字幕无码爆乳av中文| 亚洲欧美乱色情图片| 97性无码区免费| 精品亚洲AV无码一区二区三区 | 成年免费大片黄在线观看岛国| 亚洲av女电影网| 精品免费视在线观看| 亚洲成A人片777777| 一级有奶水毛片免费看| 亚洲啪啪AV无码片| 国产99视频精品免费专区| 噜噜噜亚洲色成人网站∨| 在线永久看片免费的视频| 亚洲精品无码专区久久| 免费人妻无码不卡中文字幕18禁| 一级毛片a女人刺激视频免费| 青青草原亚洲视频| 99视频在线精品免费| 亚洲中文字幕无码av在线| 午夜dj免费在线观看| 一级做α爱过程免费视频| 人人狠狠综合久久亚洲88| 91精品成人免费国产片| 亚洲午夜成人精品无码色欲| 免费播放春色aⅴ视频| 日本一区午夜艳熟免费| 亚洲依依成人精品| 国产成人在线免费观看| 精品免费久久久久国产一区| 在线电影你懂的亚洲| 国产大片91精品免费观看男同| 国产精品99爱免费视频| 亚洲国产日韩在线| 亚洲男人在线无码视频| **毛片免费观看久久精品| 水蜜桃视频在线观看免费| 亚洲高清在线播放| 免费中文字幕不卡视频| 8x网站免费入口在线观看|