用 BCEL 设计字节码

【转】用 BCEL 设计字节码
查到一篇使用BCEL了, Java 编程的动态性,第 7 部分: 用 BCEL 设计字节码,网址是 http://www-128.ibm.com/developerworks/cn/java/j-dyn0414/

字节码处理的工具也挺多,什么时候再看看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;//非静态方法slot 0处应该存储的是this
        //// 这种方式与Java如何处理方法调用有关。对于非静态的方法,每次调用的第一个(隐藏的)参数是目标对象的this引用(就是位置0储存的内容)。
        for(int i = 0;i<types.length;i++){
            slot 
+= types[i].getSize();//long,double的size为2
        }

        
        
//save time prior to invocation
        
//createInvoke在常量池增加了 addMethodref,并且addMethodref方法会先在常量池中查找是否有这个方法存在,没有则创建一系列的与此方法相关的常量池内容
        
//看看这个方法是怎么实现的,为什么此方法中INVOKEINTERFACE的要有nargs
        
//InstructionFactory的实例方法一般要用到cp在常量池中添加引用,其静态的方法一般只是创建一些指令,而这些指令不需要在常量池添加内容
        
//INVOKEXXXXX指令包括一个index指示此方法在常量池中的索引
        //// 调用静态的long java.lang.System.currentTimeMillis()方法,调用结束后函数的返回的long类型的值会压入operand stack操作数堆栈
        ilist.append(ifact.createInvoke("java.lang.System""currentTimeMillis"
                Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
//currentTimemillis()的方法结果在operand stack栈顶
        
        
//createStore方法生成了XSTORE指令,弹出operand stack栈顶的元素写入到某个局部变量中,
        
//参照之前打印出的局部变量的信息可以知道若是实例方法则 index=0处保留的this,之后是用到的方法参数的index,然后是方法内定义的局部变量
        
//slot标记在局部变量中的位置,
        
//这个局部变量没有设置名称????????
        ilist.append(InstructionFactory.createStore(Type.LONG, slot));
        
        
//call the wrapped method
        int offset =0;
        
short invoke = Constants.INVOKESTATIC;
        
//如果是实例方法则load this到栈中
        if(!methgen.isStatic()){
            
//// 如果不是调用静态函数,将调用的第一个(隐藏的)参数(目标对象的this引用)压入operand stack
            ilist.append(InstructionFactory.createLoad(Type.OBJECT, 0));
            offset 
=1;
            invoke 
= Constants.INVOKESPECIAL;
        }

        
//load 参数到栈中
        for(int i=0;i<types.length;i++){
            Type type 
= types[i];
            ilist.append(InstructionFactory.createLoad(type, offset));
// 按参数类型把参数一个个从本地变量堆栈取出,压入operand stack
            
//Long Double的size为2,void为0,其他的为1
            offset += type.getSize();
        }

        
        
//执行方法buildString$impl()
        ilist.append(ifact.createInvoke(cname, iname, 
                returnType, types, invoke));
//消耗oprand stack的this参数和length参数
                                            
//并将结果保存在操作数的栈顶
        
        
//stor result for return later
        if(returnType != Type.VOID){
            
//+2是因为之前加的的long局部变量占两个2个字,这个字是虚拟机定义的,一般为32位
            //// 将名为iname的函数返回值复制到本地变量堆栈的slot+2的位置上
            ilist.append(InstructionFactory.createStore(returnType,slot+2));
        }

        
        
//print time required for method call
        
//createFieldAccess中的 addFieldref方法先在ConstantFieldref常量池中根据type的描述符创建引用
        
//然后根据kind来创建是GETFIELD,PUTFIELD,GETSTATIC,PUTSTATIC哪个指令
        //// 获取静态对象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);//复制栈顶元素out
        ilist.append(InstructionConstants.DUP);//在复制,当前栈顶前三元素都为out引用,供下面的三次print使用out引用
        
        String text 
= "Call to method "+methgen.getName()+" took ";
        
//实际还是调的new LDC
        ilist.append(new PUSH(pgen,text));
        
        ilist.append(ifact.createInvoke(
"java.io.PrintStream"
                
"print", Type.VOID, new Type[]{Type.STRING}
                Constants.INVOKEVIRTUAL));
//消耗调一个out和栈顶的一个元素
                                         
// 调用结束,operand stack弹出一个String的引用和一个out的引用(还剩2个out),函数没有返回值
        
        ilist.append(ifact.createInvoke(
"java.lang.System"
                
"currentTimeMillis", Type.LONG, Type.NO_ARGS, 
                Constants.INVOKESTATIC));
//operand stack栈顶保留此方法的结果,即结束时间
                                         
//调用java.lang.System.currentTimeMillis()方法,调用结束后函数的返回的long类型的值会压入堆栈operand 
        
        
//load 局部变量到栈顶
        
//从本地变量堆栈的slot位置载入先前储存的long值,压入operand stack
        ilist.append(InstructionFactory.createLoad(Type.LONG, slot));
        
        
//栈顶两个元素进行减法操作,结果保存在栈顶
        
// 调用long的减法指令,弹出2个long值,并把结果压入operand stack,现在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,和减法的结果
        
        
// 将String对象" ms."放入pgen,并把其在pgen的引用(这个引用其实是字符串在常量池中的索引下标)压入operand stack(供out.print(Sting)调用的参数)
        ilist.append(new PUSH(pgen," ms."));//常量入栈,首先会判断常量池中是否有此字符串
        ilist.append(ifact.createInvoke("java.io.PrintStream"
                
"println", Type.VOID, new Type[]{Type.STRING}
                Constants.INVOKEVIRTUAL));
//消耗调最后一个out和刚入栈的" ms."
        
        
//如果返回类型不为void,则将返回结果入栈并返回
        if(returnType != Type.VOID){
            
//处理返回值,如果不为空,从本地局部对象堆栈的slot+2位置读取指定类型的返回值压入operand stack
            ilist.append(InstructionFactory.createLoad(returnType, slot+2));
        }

        
        ilist.append(InstructionFactory.createReturn(returnType));
//根据相应的返回类型创建相应的返回指令
        
        
        
//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());
        }

    }

}



字节码
-------------------------------- 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
-----------------------------------
方法访问标志
1
方法访问名称
me[i].getName()  
< init >
CONSTANT_Utf8[
1 ]( " <init> " )
方法签名
()V
CONSTANT_Utf8[
1 ]( " ()V " )
方法的参数类型
[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(
0 2 )
LocalVariable(start_pc 
=   0 , length  =   5 , index  =   0 :StringBuilder  this )

end method method method
-----------------------------------
start method method method
-----------------------------------
方法访问标志
2
方法访问名称
me[i].getName()  buildString$impl
CONSTANT_Utf8[
1 ]( " buildString$impl " )
方法签名
(I)Ljava
/ lang / String;
CONSTANT_Utf8[
1 ]( " (I)Ljava/lang/String; " )
方法的参数类型
[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(
0 5 ), LineNumber( 3 6 ), LineNumber( 8 7 ), LineNumber( 34 6 ), 
LineNumber(
42 9 )
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
-----------------------------------
方法访问标志
2
方法访问名称
me[i].getName()  buildString
CONSTANT_Utf8[
1 ]( " buildString " )
方法签名
(I)Ljava
/ lang / String;
CONSTANT_Utf8[
1 ]( " (I)Ljava/lang/String; " )
方法的参数类型
[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(
0 13 ), LineNumber( 4 14 ), LineNumber( 11 15 ), LineNumber( 23 16 ), 
LineNumber(
39 15 ), LineNumber( 42 17 )
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
-----------------------------------
方法访问标志
9
方法访问名称
me[i].getName()  main
CONSTANT_Utf8[
1 ]( " main " )
方法签名
([Ljava
/ lang / String;)V
CONSTANT_Utf8[
1 ]( " ([Ljava/lang/String;)V " )
方法的参数类型
[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(
0 21 ), LineNumber( 8 22 ), LineNumber( 13 23 ), LineNumber( 24 24 ), 
LineNumber(
36 25 ), LineNumber( 46 24 ), LineNumber( 49 22 ), LineNumber( 58 27 )

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

你可能感兴趣的:(用 BCEL 设计字节码)