随笔-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 阅读(1961) 评论(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显然是不正确的
  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: