随笔-204  评论-149  文章-0  trackbacks-0

这个最接近之前提出的API转换问题
这个需要扫描源代码找到此类的方法调用处,然后在方法调用处的前后添加指令
即将代码转换成如下形式:


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

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


        
return result;
    }

    
    
    
public static void main(String[] argv) {
        StringBuilder inst 
= new StringBuilder();
        
for (int i = 0; i < argv.length; i++{
            
            long start = System.currentTimeMillis();

            String result 
= inst.buildString(Integer.parseInt(argv[i]));
            System.out.println("Call to buildString$impl took " +
                    (System.currentTimeMillis()-start) + " ms.");

            
            System.out.println(
"Constructed string of length " +
                result.length());
        }

    }

}



转换代码如下:
先扫描这个类中的各个方法
我准备改变一下生成策略,不自己写指令了,这个自己写指令比较麻烦,但要加的代码比较多时比较容易出错,当所加的代码有if,跳转语句,自己根本就不会如何写添哪些指令,这种写类似汇编指令总是很麻烦的。

先要把加的代码自己在某个类中事先用方法写好,实例方法也好,静态方法也好,方法带有参数或者有返回值,
这些参数和返回值供调用方法中的局部变量来替换和使用。
再要添加代码的方法的前后调用这些已经写好的方法的字节码的指令序列生成InstructionList,然后再添加到使用这个方法的指令序列中

如下

public class ToolUtil {
    
    
public static long printStart() {
        System.out.println(
"start start start start");
        
long start = System.currentTimeMillis();
        
return start;
    }

    
    
public static void printEnd(String methodname,long start){
        
        System.out.println(
"Call to "+methodname+" took " +
                (System.currentTimeMillis()
-start) + " ms.");
        System.out.println(
"end end end end end end");
    }


}


原始的方法
public class StringBuilder {
    
    
    
/*
     * 要在调用了此方法的方法的代码的前后添加代码
     
*/

    
public String buildString(int length) {

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

        System.out.println(result);

        
return result;
    }


    
/*
     * 调用了buildString方法
     
*/

    
private String testInvokeMethod(){
        
        String temp 
= null;
        
        temp 
= buildString(10);
        
return temp;

    }




    
/*
     * 调用了buildString方法
     
*/

    
public static void main(String[] argv) {
        StringBuilder inst 
= new StringBuilder();
        
for (int i = 0; i < argv.length; i++{
            
            String result 
= inst.buildString(Integer.parseInt(argv[i]));
            
            System.out.println(
"Constructed string of length "
                    
+ result.length());
        }

    }

}


生成的方法为
public class StringBuilder {
    
    
    
/*
     * 要在调用了此方法的方法的代码的前后添加代码
     
*/

    
public String buildString(int length) {

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

        System.out.println(result);

        
return result;
    }


    
/*
     * 调用了buildString方法
     
*/

    
private String testInvokeMethod(){
        
        String temp 
= null;
        //调用事先写好的方法
        long startTime = ToolUtil.printStart();
        
        temp 
= buildString(10);
        
//调用事先写好的方法
        ToolUtil.printEnd("buildString", startTime);

        
        System.out.println(
"我是测试方法,我是测试方法,我是测试方法,我是测试方法");
        
return temp;

    }




    
/*
     * 调用了buildString方法
     
*/

    
public static void main(String[] argv) {
        StringBuilder inst 
= new StringBuilder();
        
for (int i = 0; i < argv.length; i++{
            
            //调用事先写好的方法
            long startTime = ToolUtil.printStart();

            String result 
= inst.buildString(Integer.parseInt(argv[i]));
            
//调用事先写好的方法
            ToolUtil.printEnd("buildString", startTime);

            
            System.out.println(
"Constructed string of length "
                    
+ result.length());
        }

    }

}

main这个调用的代码或者使用INVOKEXXXX指令实现,或者把这些调用方法的字节码指令序列加入到main的指令序列当中来实现,直接加的话可能自己事先写的方法的局部变量与main方法的局部变量会相同,而且涉及到所加的指令序列使用局部变量的问题,比如加的iload_0,istore_2就会引用现在方法的局部变量,但是现在的局部变量根本就不是这种指令所对应的类型
。所以还是使用方法调用比较方便


import java.io.FileOutputStream;

import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantNameAndType;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKEVIRTUAL;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.LocalVariableGen;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.Type;


public class BCELTiming3 {
    
    
    
    
/*
     * 扫描StringBuilder的各个方法的指令序列,在其中找Invokexxxx指令,
     * 看此指令在常量池中引用的方法引用是否是要其前后加代码的方法
     * 方法所在的类要一致,方法的名称要一致,方法的签名要一致
     * 
     
*/

    
    
/**
     * 
     * 
@param cgen 要被解析的类class文件
     * 
@param classname 要被修改的方法所在的类名称,若有包名,则为java/lang/Object类似的
     * 
@param methodname 要被修改的方法的名称
     * 
@param methodSignature 要被修改的方法的签名
     
*/

    
private static void modifyWrapper(ClassGen cgen,String classname,String methodname,String methodSignature){
        
        InstructionFactory ifact 
= new InstructionFactory(cgen);
        ConstantPoolGen pgen 
= cgen.getConstantPool();
        ConstantPool pool 
= pgen.getConstantPool();
        
        String cname 
= cgen.getClassName();
        
        
        
        Method[] methods 
= cgen.getMethods();
        
for(int i=0;i<methods.length;i++){
            Method tempMethod 
= methods[i];
            
            MethodGen tempMethodGen 
= new MethodGen(tempMethod,cname,pgen);
            
            InstructionList tempList 
= tempMethodGen.getInstructionList();
            tempList.iterator();
            Instruction[] tempInstructions 
= tempList.getInstructions();
            InstructionHandle[] tempInHandles 
= tempList.getInstructionHandles();
            
for(int j=0;j<tempInHandles.length;j++){
                InstructionHandle ihandle 
= tempInHandles[j];
                Instruction nowInstruction 
= ihandle.getInstruction();
                
if(nowInstruction.getOpcode()==Constants.INVOKEVIRTUAL){
                    INVOKEVIRTUAL invokeVirtual 
= (INVOKEVIRTUAL)nowInstruction;
                    ConstantMethodref cmr 
= (ConstantMethodref)pgen.getConstant(invokeVirtual.getIndex());
                    
                    ConstantClass cc 
= (ConstantClass)pgen.getConstant(cmr.getClassIndex());
                    String nowClassName 
= cc.getBytes(pgen.getConstantPool());
                    ConstantNameAndType cnt 
= (ConstantNameAndType)pgen.getConstant(cmr.getNameAndTypeIndex());
                    String nowMethodName 
= cnt.getName(pgen.getConstantPool());
                    String nowMethodSignature 
= cnt.getSignature(pgen.getConstantPool());
                    
                    
//判断此方法的所属的类,方法的名称,方法的签名是否与所要加的一致(I)Ljava/lang/String;
                    if(nowClassName.equals(classname) && nowMethodName.equals(methodname) && nowMethodSignature.equals(methodSignature)){
                        
                        cgen.removeMethod(tempMethodGen.getMethod());
                        
                        
//找到此方法在list的位置
                        InstructionList beforeList = new InstructionList();
                        
//先加一个局部变量保存starttime的值
                        LocalVariableGen lvg = tempMethodGen.addLocalVariable("starttime", Type.LONG, nullnull);
                        beforeList.append(ifact.createInvoke(
"ToolUtil""printStart", Type.LONG, Type.NO_ARGS, Constants.INVOKESTATIC));
                        beforeList.append(InstructionFactory.createStore(Type.LONG, lvg.getIndex()));
                        tempList.insert(ihandle.getPrev().getPrev(), beforeList);
                        
                        
//加方法后的代码
                        InstructionList afterList = new InstructionList();
                        afterList.append(ifact.createConstant(methodname));
                        afterList.append(ifact.createLoad(Type.LONG, lvg.getIndex()));
                        afterList.append(ifact.createInvoke(
"ToolUtil""printEnd", Type.VOID, new Type[]{Type.STRING,Type.LONG}, Constants.INVOKESTATIC));
                        tempList.insert(ihandle.getNext().getNext(), afterList);
                        
                        
                        
//finalize the construted method
                        tempMethodGen.stripAttributes(false);
                        tempMethodGen.setMaxStack();
                        tempMethodGen.setMaxLocals();

                        cgen.addMethod(tempMethodGen.getMethod());
                        
                        System.out.println(tempMethodGen.getInstructionList());
                        System.out.println();
                        System.out.println();
                        
                        
                    }

                }

            }

            
//            tempList.setPositions();
//            tempList.findHandle(pos);
            
        }

            
    }


    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) {
        
        args[
0]="D:\\java to eclipse\\javaeclipsestudy\\workspace\\BCELTest\\bin\\StringBuilder.class";
        
        
if(args.length==1 && args[0].endsWith(".class")){
            
try{
                JavaClass jclas 
= new ClassParser(args[0]).parse();
                
                ClassGen cgen 
= new ClassGen(jclas);
                
                modifyWrapper(cgen,
"StringBuilder","buildString","(I)Ljava/lang/String;");
                
                
                cgen.getJavaClass().dump(args[
0]);
            }
catch(Exception e){
                e.printStackTrace();
            }

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


    }


}



posted on 2009-08-13 23:10 Frank_Fang 阅读(1706) 评论(3)  编辑  收藏 所属分类: bcel javassist

评论:
# re: 用 BCEL 设计字节码(三)直接在方法的调用处添加方法 2009-08-16 18:37 | Frank_Fang
原来方法的字节码
--------------------------------33
--------------------------------33
0
2
CONSTANT_Utf8[1]("SourceFile")
true
CONSTANT_Utf8[1]("StringBuilder.java")
1
StringBuilder.java
StringBuilder.java
---------------------------------------------------------------------------
1:CONSTANT_Class[7](name_index = 2)
2:CONSTANT_Utf8[1]("StringBuilder")
3:CONSTANT_Class[7](name_index = 4)
4:CONSTANT_Utf8[1]("java/lang/Object")
5:CONSTANT_Utf8[1]("<init>")
6:CONSTANT_Utf8[1]("()V")
7:CONSTANT_Utf8[1]("Code")
8:CONSTANT_Methodref[10](class_index = 3, name_and_type_index = 9)
9:CONSTANT_NameAndType[12](name_index = 5, signature_index = 6)
10:CONSTANT_Utf8[1]("LineNumberTable")
11:CONSTANT_Utf8[1]("LocalVariableTable")
12:CONSTANT_Utf8[1]("this")
13:CONSTANT_Utf8[1]("LStringBuilder;")
14:CONSTANT_Utf8[1]("buildString")
15:CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
16:CONSTANT_String[8](string_index = 17)
17:CONSTANT_Utf8[1]("")
18:CONSTANT_Class[7](name_index = 19)
19:CONSTANT_Utf8[1]("java/lang/StringBuilder")
20:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 23)
21:CONSTANT_Class[7](name_index = 22)
22:CONSTANT_Utf8[1]("java/lang/String")
23:CONSTANT_NameAndType[12](name_index = 24, signature_index = 25)
24:CONSTANT_Utf8[1]("valueOf")
25:CONSTANT_Utf8[1]("(Ljava/lang/Object;)Ljava/lang/String;")
26:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 27)
27:CONSTANT_NameAndType[12](name_index = 5, signature_index = 28)
28:CONSTANT_Utf8[1]("(Ljava/lang/String;)V")
29:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 30)
30:CONSTANT_NameAndType[12](name_index = 31, signature_index = 32)
31:CONSTANT_Utf8[1]("append")
32:CONSTANT_Utf8[1]("(C)Ljava/lang/StringBuilder;")
33:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 34)
34:CONSTANT_NameAndType[12](name_index = 35, signature_index = 36)
35:CONSTANT_Utf8[1]("toString")
36:CONSTANT_Utf8[1]("()Ljava/lang/String;")
37:CONSTANT_Fieldref[9](class_index = 38, name_and_type_index = 40)
*********************ConstantFieldref start**********************
cc.toString : CONSTANT_Class[7](name_index = 39)
java/lang/System
cnat.toString : CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
out
Ljava/io/PrintStream;
**********************ConstantFieldref end*******************************
38:CONSTANT_Class[7](name_index = 39)
39:CONSTANT_Utf8[1]("java/lang/System")
40:CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
41:CONSTANT_Utf8[1]("out")
42:CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
43:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 46)
44:CONSTANT_Class[7](name_index = 45)
45:CONSTANT_Utf8[1]("java/io/PrintStream")
46:CONSTANT_NameAndType[12](name_index = 47, signature_index = 28)
47:CONSTANT_Utf8[1]("println")
48:CONSTANT_Utf8[1]("length")
49:CONSTANT_Utf8[1]("I")
50:CONSTANT_Utf8[1]("result")
51:CONSTANT_Utf8[1]("Ljava/lang/String;")
52:CONSTANT_Utf8[1]("i")
53:CONSTANT_Utf8[1]("testInvokeMethod")
54:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 55)
55:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
56:CONSTANT_String[8](string_index = 57)
57:CONSTANT_Utf8[1]("我是测试方法,我是测试方法,我是测试方法,我是测试方法")
58:CONSTANT_Utf8[1]("temp")
59:CONSTANT_Utf8[1]("main")
60:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
61:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
62:CONSTANT_Methodref[10](class_index = 63, name_and_type_index = 65)
63:CONSTANT_Class[7](name_index = 64)
64:CONSTANT_Utf8[1]("java/lang/Integer")
65:CONSTANT_NameAndType[12](name_index = 66, signature_index = 67)
66:CONSTANT_Utf8[1]("parseInt")
67:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
68:CONSTANT_String[8](string_index = 69)
69:CONSTANT_Utf8[1]("Constructed string of length ")
70:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 71)
71:CONSTANT_NameAndType[12](name_index = 48, signature_index = 72)
72:CONSTANT_Utf8[1]("()I")
73:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 74)
74:CONSTANT_NameAndType[12](name_index = 31, signature_index = 75)
75:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
76:CONSTANT_Utf8[1]("argv")
77:CONSTANT_Utf8[1]("[Ljava/lang/String;")
78:CONSTANT_Utf8[1]("inst")
79:CONSTANT_Utf8[1]("SourceFile")
80:CONSTANT_Utf8[1]("StringBuilder.java")
--------------------------域----------------------------
-----------域的长度,此类定义的成员变量的个数-------------0




start method method method-----------------------------------
方法访问标志
1
方法访问名称
<init>
CONSTANT_Utf8[1]("<init>")
方法签名
()V
CONSTANT_Utf8[1]("()V")
方法的参数类型
方法的返回类型
void
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 47
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 5
给出该方法在执行中任何点操作数栈上字的最大个数 1
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 1
code的字节信息调用code.getCode()返回byte[] [B@1571886
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======1
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=5| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
完整的code.toString的信息
public void <init>()
Code(max_stack = 1, max_locals = 1, code_length = 5)
0: aload_0
1: invokespecial java.lang.Object.<init> ()V (8)
4: return

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

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


start method method method-----------------------------------
方法访问标志
1
方法访问名称
buildString
CONSTANT_Utf8[1]("buildString")
方法签名
(I)Ljava/lang/String;
CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
方法的参数类型
int方法的返回类型
java.lang.String
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 143
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 51
给出该方法在执行中任何点操作数栈上字的最大个数 3
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 4
code的字节信息调用code.getCode()返回byte[] [B@1c184f4
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======4
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=48 | lv.getName()=length| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=1
--------------------第 2 个局部变量的信息
lv.getStartPC()=3| lv.getLength=48| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=2
--------------------第 3 个局部变量的信息
lv.getStartPC()=5| lv.getLength=37| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=3
完整的code.toString的信息
public String buildString(int length)
Code(max_stack = 3, max_locals = 4, code_length = 51)
0: ldc "" (16)
2: astore_2
3: iconst_0
4: istore_3
5: goto #37
8: new <java.lang.StringBuilder> (18)
11: dup
12: aload_2
13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
19: iload_3
20: bipush 26
22: irem
23: bipush 97
25: iadd
26: i2c
27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
33: astore_2
34: iinc %3 1
37: iload_3
38: iload_1
39: if_icmplt #8
42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
45: aload_2
46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
49: aload_2
50: areturn

Attribute(s) =
LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
LineNumber(42, 13), LineNumber(49, 15)
LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
LocalVariable(start_pc = 0, length = 51, index = 1:int length)
LocalVariable(start_pc = 3, length = 48, index = 2:String result)
LocalVariable(start_pc = 5, length = 37, index = 3:int i)

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


start method method method-----------------------------------
方法访问标志
2
方法访问名称
testInvokeMethod
CONSTANT_Utf8[1]("testInvokeMethod")
方法签名
()Ljava/lang/String;
CONSTANT_Utf8[1]("()Ljava/lang/String;")
方法的参数类型
方法的返回类型
java.lang.String
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 83
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 19
给出该方法在执行中任何点操作数栈上字的最大个数 2
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 2
code的字节信息调用code.getCode()返回byte[] [B@1ffbd68
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======2
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=19| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=2| lv.getLength=17| lv.getNameIndex()=58 | lv.getName()=temp| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=1
完整的code.toString的信息
private String testInvokeMethod()
Code(max_stack = 2, max_locals = 2, code_length = 19)
0: aconst_null
1: astore_1
2: aload_0
3: bipush 10
5: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
8: astore_1
9: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
12: ldc "我是测试方法,我是测试方法,我是测试方法,我是测试方法" (56)
14: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
17: aload_1
18: areturn

Attribute(s) =
LineNumber(0, 27), LineNumber(2, 31), LineNumber(9, 35), LineNumber(17, 37)

LocalVariable(start_pc = 0, length = 19, index = 0:StringBuilder this)
LocalVariable(start_pc = 2, length = 17, index = 1:String temp)

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


start method method method-----------------------------------
方法访问标志
9
方法访问名称
main
CONSTANT_Utf8[1]("main")
方法签名
([Ljava/lang/String;)V
CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
方法的参数类型
java.lang.String[]方法的返回类型
void
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 159
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 59
给出该方法在执行中任何点操作数栈上字的最大个数 4
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 4
code的字节信息调用code.getCode()返回byte[] [B@ec16a4
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======4
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=59| lv.getNameIndex()=76 | lv.getName()=argv| lv.getSignatureIndex()=77 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=8| lv.getLength=51| lv.getNameIndex()=78 | lv.getName()=inst| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=1
--------------------第 2 个局部变量的信息
lv.getStartPC()=10| lv.getLength=48| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=2
--------------------第 3 个局部变量的信息
lv.getStartPC()=24| lv.getLength=25| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=3
完整的code.toString的信息
public static void main(String[] argv)
Code(max_stack = 4, max_locals = 4, code_length = 59)
0: new <StringBuilder> (1)
3: dup
4: invokespecial StringBuilder.<init> ()V (61)
7: astore_1
8: iconst_0
9: istore_2
10: goto #52
13: aload_1
14: aload_0
15: iload_2
16: aaload
17: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (62)
20: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
23: astore_3
24: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
27: new <java.lang.StringBuilder> (18)
30: dup
31: ldc "Constructed string of length " (68)
33: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
36: aload_3
37: invokevirtual java.lang.String.length ()I (70)
40: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (73)
43: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
49: iinc %2 1
52: iload_2
53: aload_0
54: arraylength
55: if_icmplt #13
58: return

Attribute(s) =
LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 52), LineNumber(24, 56),
LineNumber(36, 57), LineNumber(46, 56), LineNumber(49, 48), LineNumber(58, 59)

LocalVariable(start_pc = 0, length = 59, index = 0:String[] argv)
LocalVariable(start_pc = 8, length = 51, index = 1:StringBuilder inst)
LocalVariable(start_pc = 10, length = 48, index = 2:int i)
LocalVariable(start_pc = 24, length = 25, index = 3:String result)

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


  回复  更多评论
  
# re: 用 BCEL 设计字节码(三)直接在方法的调用处添加方法 2009-08-16 18:39 | Frank_Fang
自己在程序加调用语句用编译器生成的字节码
--------------------------------33
--------------------------------33
0
2
CONSTANT_Utf8[1]("SourceFile")
true
CONSTANT_Utf8[1]("StringBuilder.java")
1
StringBuilder.java
StringBuilder.java
---------------------------------------------------------------------------
1:CONSTANT_Class[7](name_index = 2)
2:CONSTANT_Utf8[1]("StringBuilder")
3:CONSTANT_Class[7](name_index = 4)
4:CONSTANT_Utf8[1]("java/lang/Object")
5:CONSTANT_Utf8[1]("<init>")
6:CONSTANT_Utf8[1]("()V")
7:CONSTANT_Utf8[1]("Code")
8:CONSTANT_Methodref[10](class_index = 3, name_and_type_index = 9)
9:CONSTANT_NameAndType[12](name_index = 5, signature_index = 6)
10:CONSTANT_Utf8[1]("LineNumberTable")
11:CONSTANT_Utf8[1]("LocalVariableTable")
12:CONSTANT_Utf8[1]("this")
13:CONSTANT_Utf8[1]("LStringBuilder;")
14:CONSTANT_Utf8[1]("buildString")
15:CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
16:CONSTANT_String[8](string_index = 17)
17:CONSTANT_Utf8[1]("")
18:CONSTANT_Class[7](name_index = 19)
19:CONSTANT_Utf8[1]("java/lang/StringBuilder")
20:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 23)
21:CONSTANT_Class[7](name_index = 22)
22:CONSTANT_Utf8[1]("java/lang/String")
23:CONSTANT_NameAndType[12](name_index = 24, signature_index = 25)
24:CONSTANT_Utf8[1]("valueOf")
25:CONSTANT_Utf8[1]("(Ljava/lang/Object;)Ljava/lang/String;")
26:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 27)
27:CONSTANT_NameAndType[12](name_index = 5, signature_index = 28)
28:CONSTANT_Utf8[1]("(Ljava/lang/String;)V")
29:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 30)
30:CONSTANT_NameAndType[12](name_index = 31, signature_index = 32)
31:CONSTANT_Utf8[1]("append")
32:CONSTANT_Utf8[1]("(C)Ljava/lang/StringBuilder;")
33:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 34)
34:CONSTANT_NameAndType[12](name_index = 35, signature_index = 36)
35:CONSTANT_Utf8[1]("toString")
36:CONSTANT_Utf8[1]("()Ljava/lang/String;")
37:CONSTANT_Fieldref[9](class_index = 38, name_and_type_index = 40)
*********************ConstantFieldref start**********************
cc.toString : CONSTANT_Class[7](name_index = 39)
java/lang/System
cnat.toString : CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
out
Ljava/io/PrintStream;
**********************ConstantFieldref end*******************************
38:CONSTANT_Class[7](name_index = 39)
39:CONSTANT_Utf8[1]("java/lang/System")
40:CONSTANT_NameAndType[12](name_index = 41, signature_index = 42)
41:CONSTANT_Utf8[1]("out")
42:CONSTANT_Utf8[1]("Ljava/io/PrintStream;")
43:CONSTANT_Methodref[10](class_index = 44, name_and_type_index = 46)
44:CONSTANT_Class[7](name_index = 45)
45:CONSTANT_Utf8[1]("java/io/PrintStream")
46:CONSTANT_NameAndType[12](name_index = 47, signature_index = 28)
47:CONSTANT_Utf8[1]("println")
48:CONSTANT_Utf8[1]("length")
49:CONSTANT_Utf8[1]("I")
50:CONSTANT_Utf8[1]("result")
51:CONSTANT_Utf8[1]("Ljava/lang/String;")
52:CONSTANT_Utf8[1]("i")
53:CONSTANT_Utf8[1]("testInvokeMethod")
54:CONSTANT_Methodref[10](class_index = 55, name_and_type_index = 57)
55:CONSTANT_Class[7](name_index = 56)
56:CONSTANT_Utf8[1]("ToolUtil")
57:CONSTANT_NameAndType[12](name_index = 58, signature_index = 59)
58:CONSTANT_Utf8[1]("printStart")
59:CONSTANT_Utf8[1]("()J")
60:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 61)
61:CONSTANT_NameAndType[12](name_index = 14, signature_index = 15)
62:CONSTANT_String[8](string_index = 14)
63:CONSTANT_Methodref[10](class_index = 55, name_and_type_index = 64)
64:CONSTANT_NameAndType[12](name_index = 65, signature_index = 66)
65:CONSTANT_Utf8[1]("printEnd")
66:CONSTANT_Utf8[1]("(Ljava/lang/String;J)V")
67:CONSTANT_String[8](string_index = 68)
68:CONSTANT_Utf8[1]("我是测试方法,我是测试方法,我是测试方法,我是测试方法")
69:CONSTANT_Utf8[1]("temp")
70:CONSTANT_Utf8[1]("startTime")
71:CONSTANT_Utf8[1]("J")
72:CONSTANT_Utf8[1]("main")
73:CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
74:CONSTANT_Methodref[10](class_index = 1, name_and_type_index = 9)
75:CONSTANT_Methodref[10](class_index = 76, name_and_type_index = 78)
76:CONSTANT_Class[7](name_index = 77)
77:CONSTANT_Utf8[1]("java/lang/Integer")
78:CONSTANT_NameAndType[12](name_index = 79, signature_index = 80)
79:CONSTANT_Utf8[1]("parseInt")
80:CONSTANT_Utf8[1]("(Ljava/lang/String;)I")
81:CONSTANT_String[8](string_index = 82)
82:CONSTANT_Utf8[1]("Constructed string of length ")
83:CONSTANT_Methodref[10](class_index = 21, name_and_type_index = 84)
84:CONSTANT_NameAndType[12](name_index = 48, signature_index = 85)
85:CONSTANT_Utf8[1]("()I")
86:CONSTANT_Methodref[10](class_index = 18, name_and_type_index = 87)
87:CONSTANT_NameAndType[12](name_index = 31, signature_index = 88)
88:CONSTANT_Utf8[1]("(I)Ljava/lang/StringBuilder;")
89:CONSTANT_Utf8[1]("argv")
90:CONSTANT_Utf8[1]("[Ljava/lang/String;")
91:CONSTANT_Utf8[1]("inst")
92:CONSTANT_Utf8[1]("SourceFile")
93:CONSTANT_Utf8[1]("StringBuilder.java")
--------------------------域----------------------------
-----------域的长度,此类定义的成员变量的个数-------------0




start method method method-----------------------------------
方法访问标志
1
方法访问名称
<init>
CONSTANT_Utf8[1]("<init>")
方法签名
()V
CONSTANT_Utf8[1]("()V")
方法的参数类型
方法的返回类型
void
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 47
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 5
给出该方法在执行中任何点操作数栈上字的最大个数 1
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 1
code的字节信息调用code.getCode()返回byte[] [B@1571886
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======1
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=5| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
完整的code.toString的信息
public void <init>()
Code(max_stack = 1, max_locals = 1, code_length = 5)
0: aload_0
1: invokespecial java.lang.Object.<init> ()V (8)
4: return

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

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


start method method method-----------------------------------
方法访问标志
1
方法访问名称
buildString
CONSTANT_Utf8[1]("buildString")
方法签名
(I)Ljava/lang/String;
CONSTANT_Utf8[1]("(I)Ljava/lang/String;")
方法的参数类型
int方法的返回类型
java.lang.String
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 143
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 51
给出该方法在执行中任何点操作数栈上字的最大个数 3
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 4
code的字节信息调用code.getCode()返回byte[] [B@1c184f4
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======4
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=0| lv.getLength=51| lv.getNameIndex()=48 | lv.getName()=length| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=1
--------------------第 2 个局部变量的信息
lv.getStartPC()=3| lv.getLength=48| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=2
--------------------第 3 个局部变量的信息
lv.getStartPC()=5| lv.getLength=37| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=3
完整的code.toString的信息
public String buildString(int length)
Code(max_stack = 3, max_locals = 4, code_length = 51)
0: ldc "" (16)
2: astore_2
3: iconst_0
4: istore_3
5: goto #37
8: new <java.lang.StringBuilder> (18)
11: dup
12: aload_2
13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
19: iload_3
20: bipush 26
22: irem
23: bipush 97
25: iadd
26: i2c
27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
33: astore_2
34: iinc %3 1
37: iload_3
38: iload_1
39: if_icmplt #8
42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
45: aload_2
46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
49: aload_2
50: areturn

Attribute(s) =
LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
LineNumber(42, 13), LineNumber(49, 15)
LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
LocalVariable(start_pc = 0, length = 51, index = 1:int length)
LocalVariable(start_pc = 3, length = 48, index = 2:String result)
LocalVariable(start_pc = 5, length = 37, index = 3:int i)

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


start method method method-----------------------------------
方法访问标志
2
方法访问名称
testInvokeMethod
CONSTANT_Utf8[1]("testInvokeMethod")
方法签名
()Ljava/lang/String;
CONSTANT_Utf8[1]("()Ljava/lang/String;")
方法的参数类型
方法的返回类型
java.lang.String
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 111
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 29
给出该方法在执行中任何点操作数栈上字的最大个数 3
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 4
code的字节信息调用code.getCode()返回byte[] [B@1ffbd68
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======3
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=29| lv.getNameIndex()=12 | lv.getName()=this| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=2| lv.getLength=27| lv.getNameIndex()=69 | lv.getName()=temp| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=1
--------------------第 2 个局部变量的信息
lv.getStartPC()=6| lv.getLength=23| lv.getNameIndex()=70 | lv.getName()=startTime| lv.getSignatureIndex()=71 | lv.getSignature()=J |lv.getIndex()=2
完整的code.toString的信息
private String testInvokeMethod()
Code(max_stack = 3, max_locals = 4, code_length = 29)
0: aconst_null
1: astore_1
2: invokestatic ToolUtil.printStart ()J (54)
5: lstore_2
6: aload_0
7: bipush 10
9: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (60)
12: astore_1
13: ldc "buildString" (62)
15: lload_2
16: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (63)
19: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
22: ldc "我是测试方法,我是测试方法,我是测试方法,我是测试方法" (67)
24: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
27: aload_1
28: areturn

Attribute(s) =
LineNumber(0, 27), LineNumber(2, 29), LineNumber(6, 31), LineNumber(13, 33),
LineNumber(19, 35), LineNumber(27, 37)
LocalVariable(start_pc = 0, length = 29, index = 0:StringBuilder this)
LocalVariable(start_pc = 2, length = 27, index = 1:String temp)
LocalVariable(start_pc = 6, length = 23, index = 2:long startTime)

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


start method method method-----------------------------------
方法访问标志
9
方法访问名称
main
CONSTANT_Utf8[1]("main")
方法签名
([Ljava/lang/String;)V
CONSTANT_Utf8[1]("([Ljava/lang/String;)V")
方法的参数类型
java.lang.String[]方法的返回类型
void
方法的ExceptionTable属性----------方法的throws声明的异常信息------------------------
exceptionTable==null true
方法的Code---------------------------------------------
7
CONSTANT_Utf8[1]("Code")
code.getLength() 属性结构中attribute length 的长度 189
code.getCode().length 属性结构中的code数组的长度 code_length 的长度 71
给出该方法在执行中任何点操作数栈上字的最大个数 4
给出该方法使用的局部变量的个数,包括调用时传递给方法的参数 6
code的字节信息调用code.getCode()返回byte[] [B@ec16a4
ce.length===========0
code 内部结构中的各异常信息结构------------方法内部的try 块catch的信息----------
方法的Code的LineNumberTable
方法的Code的LocalVariableTable
LocalVariableTable
localvariableTable==null false
lvs==null false
lvs.length======5
--------------------第 0 个局部变量的信息
lv.getStartPC()=0| lv.getLength=71| lv.getNameIndex()=89 | lv.getName()=argv| lv.getSignatureIndex()=90 | lv.getSignature()=[Ljava/lang/String; |lv.getIndex()=0
--------------------第 1 个局部变量的信息
lv.getStartPC()=8| lv.getLength=63| lv.getNameIndex()=91 | lv.getName()=inst| lv.getSignatureIndex()=13 | lv.getSignature()=LStringBuilder; |lv.getIndex()=1
--------------------第 2 个局部变量的信息
lv.getStartPC()=10| lv.getLength=60| lv.getNameIndex()=52 | lv.getName()=i| lv.getSignatureIndex()=49 | lv.getSignature()=I |lv.getIndex()=2
--------------------第 3 个局部变量的信息
lv.getStartPC()=17| lv.getLength=44| lv.getNameIndex()=70 | lv.getName()=startTime| lv.getSignatureIndex()=71 | lv.getSignature()=J |lv.getIndex()=3
--------------------第 4 个局部变量的信息
lv.getStartPC()=29| lv.getLength=32| lv.getNameIndex()=50 | lv.getName()=result| lv.getSignatureIndex()=51 | lv.getSignature()=Ljava/lang/String; |lv.getIndex()=5
完整的code.toString的信息
public static void main(String[] argv)
Code(max_stack = 4, max_locals = 6, code_length = 71)
0: new <StringBuilder> (1)
3: dup
4: invokespecial StringBuilder.<init> ()V (74)
7: astore_1
8: iconst_0
9: istore_2
10: goto #64
13: invokestatic ToolUtil.printStart ()J (54)
16: lstore_3
17: aload_1
18: aload_0
19: iload_2
20: aaload
21: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (75)
24: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (60)
27: astore %5
29: ldc "buildString" (62)
31: lload_3
32: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (63)
35: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
38: new <java.lang.StringBuilder> (18)
41: dup
42: ldc "Constructed string of length " (81)
44: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
47: aload %5
49: invokevirtual java.lang.String.length ()I (83)
52: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (86)
55: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
58: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
61: iinc %2 1
64: iload_2
65: aload_0
66: arraylength
67: if_icmplt #13
70: return

Attribute(s) =
LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 51), LineNumber(17, 52),
LineNumber(29, 54), LineNumber(35, 56), LineNumber(47, 57), LineNumber(58, 56),
LineNumber(61, 48), LineNumber(70, 59)
LocalVariable(start_pc = 0, length = 71, index = 0:String[] argv)
LocalVariable(start_pc = 8, length = 63, index = 1:StringBuilder inst)
LocalVariable(start_pc = 10, length = 60, index = 2:int i)
LocalVariable(start_pc = 17, length = 44, index = 3:long startTime)
LocalVariable(start_pc = 29, length = 32, index = 5:String result)

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


  回复  更多评论
  
# re: 用 BCEL 设计字节码(三)直接在方法的调用处添加方法 2009-08-16 18:46 | Frank_Fang
自己生成的字节码,注意看与上一个main中的区别
因为main中调用buildString(Integer.parseInt(argv[i]))时,方法的参数是使用语句产生的,而我在自己生成字节码时,是在buildString的invokevirtual的上两个指令加的我自己的指令,与编译器产生的有的区别

完整的code.toString的信息
public String buildString(int length)
Code(max_stack = 3, max_locals = 4, code_length = 51)
0: ldc "" (16)
2: astore_2
3: iconst_0
4: istore_3
5: goto #37
8: new <java.lang.StringBuilder> (18)
11: dup
12: aload_2
13: invokestatic java.lang.String.valueOf (Ljava/lang/Object;)Ljava/lang/String; (20)
16: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
19: iload_3
20: bipush 26
22: irem
23: bipush 97
25: iadd
26: i2c
27: invokevirtual java.lang.StringBuilder.append (C)Ljava/lang/StringBuilder; (29)
30: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
33: astore_2
34: iinc %3 1
37: iload_3
38: iload_1
39: if_icmplt #8
42: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
45: aload_2
46: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
49: aload_2
50: areturn

Attribute(s) =
LineNumber(0, 9), LineNumber(3, 10), LineNumber(8, 11), LineNumber(34, 10),
LineNumber(42, 13), LineNumber(49, 15)
LocalVariable(start_pc = 0, length = 51, index = 0:StringBuilder this)
LocalVariable(start_pc = 0, length = 51, index = 1:int length)
LocalVariable(start_pc = 3, length = 48, index = 2:String result)
LocalVariable(start_pc = 5, length = 37, index = 3:int i)

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


完整的code.toString的信息
private String testInvokeMethod()
Code(max_stack = 3, max_locals = 4, code_length = 29)
0: aconst_null
1: astore_1
2: invokestatic ToolUtil.printStart ()J (86)
5: lstore_2
6: aload_0
7: bipush 10
9: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
12: astore_1
13: ldc "buildString" (87)
15: lload_2
16: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (91)
19: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
22: ldc "我是测试方法,我是测试方法,我是测试方法,我是测试方法" (56)
24: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
27: aload_1
28: areturn

Attribute(s) =
LocalVariable(start_pc = 0, length = 29, index = 0:StringBuilder this)
LocalVariable(start_pc = 6, length = 23, index = 1:String temp)
LocalVariable(start_pc = 0, length = 29, index = 2:long starttime)
LineNumber(0, 27), LineNumber(6, 31), LineNumber(19, 35), LineNumber(27, 37)


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



完整的code.toString的信息
public static void main(String[] argv)
Code(max_stack = 5, max_locals = 6, code_length = 71)
0: new <StringBuilder> (1)
3: dup
4: invokespecial StringBuilder.<init> ()V (61)
7: astore_1
8: iconst_0
9: istore_2
10: goto #64
13: aload_1
14: aload_0
15: iload_2
16: invokestatic ToolUtil.printStart ()J (86)
19: lstore %4
21: aaload
22: invokestatic java.lang.Integer.parseInt (Ljava/lang/String;)I (62)
25: invokevirtual StringBuilder.buildString (I)Ljava/lang/String; (54)
28: astore_3
29: ldc "buildString" (87)
31: lload %4
33: invokestatic ToolUtil.printEnd (Ljava/lang/String;J)V (91)
36: getstatic java.lang.System.out Ljava/io/PrintStream; (37)
39: new <java.lang.StringBuilder> (18)
42: dup
43: ldc "Constructed string of length " (68)
45: invokespecial java.lang.StringBuilder.<init> (Ljava/lang/String;)V (26)
48: aload_3
49: invokevirtual java.lang.String.length ()I (70)
52: invokevirtual java.lang.StringBuilder.append (I)Ljava/lang/StringBuilder; (73)
55: invokevirtual java.lang.StringBuilder.toString ()Ljava/lang/String; (33)
58: invokevirtual java.io.PrintStream.println (Ljava/lang/String;)V (43)
61: iinc %2 1
64: iload_2
65: aload_0
66: arraylength
67: if_icmplt #13
70: return

Attribute(s) =
LocalVariable(start_pc = 0, length = 71, index = 0:String[] argv)
LocalVariable(start_pc = 8, length = 63, index = 1:StringBuilder inst)
LocalVariable(start_pc = 10, length = 61, index = 2:int i)
LocalVariable(start_pc = 36, length = 28, index = 3:String result)
LocalVariable(start_pc = 0, length = 71, index = 4:long starttime)
LineNumber(0, 47), LineNumber(8, 48), LineNumber(13, 52), LineNumber(36, 56),
LineNumber(48, 57), LineNumber(58, 56), LineNumber(61, 48), LineNumber(70, 59)


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


  回复  更多评论
  

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


网站导航: