通过javassist向编译后的指定类中的方法注入时间戳

实现步骤如下:
1.javac -cp .;./javassist.jar JassistTiming.java

2.javac StringBuilder.java

3.java StringBuilder 1000 2000 4000 8000 16000
Constructed string of length 1000
Constructed string of length 2000
Constructed string of length 4000
Constructed string of length 8000
Constructed string of length 16000

4.java -cp .;./javassist.jar JassistTiming StringBuilder buildString
begin to main of JassistTiming
begin to addTiming
Interceptor method body:
{
long start = System.currentTimeMillis();
java.lang.String result = buildString$impl($$);
System.out.println("Call to method buildString took " +
(System.currentTimeMillis()-start) + " ms.");
return result;
}
Added timing to method StringBuilder.buildString

5.java StringBuilder 1000 2000 4000 8000 16000

扩展:如果需要对指定的jar包中的某个类的方法注入时间戳的话,可按如下方式执行。
6.java -cp .;./javassist.jar;apusic.jar;javaee.jar JassistTiming com.apusic.web.http.ConnectionHandler doTrace

其中:
(1)需要提供javassist的jar包javassist.jar,
(2)在构造指定jar包的类时,可能需要引入第三方jar包,如:javaee.jar
(3)指定要注入的类的包路径,如:com.apusic.web.http.ConnectionHandler
(4)指定要注入的类的方法名,不需要带参数,仅方法名标识。
(5)注意使用-cp时,要指定当前目录【.】。

7.最后:向方法中注入时间戳可用于跟踪某个方法执行耗时的统计,可作为分析调优的诊断方法。

8.说明:
(1)javassist去http://www.jboss.org/javassist下载;
(2)JassistTiming.java代码清单:
**************************************
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.ClassPool;
import javassist.CannotCompileException;
import javassist.NotFoundException;
import java.io.IOException;

public class JassistTiming
{
    public static void main(String[] argv) {
  System.out.println("begin to main of JassistTiming");
        if (argv.length == 2) {
            try {
              
                // start by getting the class file and method
                CtClass clas = ClassPool.getDefault().get(argv[0]);
                if (clas == null) {
                    System.err.println("Class " + argv[0] + " not found");
                } else {
                  
                    // add timing interceptor to the class
                    addTiming(clas, argv[1]);
                    clas.writeFile();
                    System.out.println("Added timing to method " +
                        argv[0] + "." + argv[1]);
                  
                }
              
            } catch (CannotCompileException ex) {
                ex.printStackTrace();
            } catch (NotFoundException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
          
        } else {
            System.out.println("Usage: JassistTiming class method-name");
        }
    }
  
    private static void addTiming(CtClass clas, String mname)
        throws NotFoundException, CannotCompileException {

  System.out.println("begin to addTiming");
      
        //  get the method information (throws exception if method with
        //  given name is not declared directly by this class, returns
        //  arbitrary choice if more than one with the given name)
        CtMethod mold = clas.getDeclaredMethod(mname);
      
        //  rename old method to synthetic name, then duplicate the
        //  method with original name for use as interceptor
        String nname = mname+"$impl";
        mold.setName(nname);
        CtMethod mnew = CtNewMethod.copy(mold, mname, clas, null);
      
        //  start the body text generation by saving the start time
        //  to a local variable, then call the timed method; the
        //  actual code generated needs to depend on whether the
        //  timed method returns a value
        String type = mold.getReturnType().getName();
        StringBuffer body = new StringBuffer();
        body.append("{\nlong start = System.currentTimeMillis();\n");
        if (!"void".equals(type)) {
            body.append(type + " result = ");
        }
        body.append(nname + "($$);\n");
      
        //  finish body text generation with call to print the timing
        //  information, and return saved value (if not void)
        body.append("System.out.println(\"Call to method " + mname +
            " took \" +\n (System.currentTimeMillis()-start) + " +
            "\" ms.\");\n");
        if (!"void".equals(type)) {
            body.append("return result;\n");
        }
        body.append("}");
      
        //  replace the body of the interceptor method with generated
        //  code block and add it to class
        mnew.setBody(body.toString());
        clas.addMethod(mnew);
      
        //  print the generated code block just to show what was done
        System.out.println("Interceptor method body:");
        System.out.println(body.toString());
    }
}
**************************************
(3)StringBuilder.java代码清单:
**************************************
public class StringBuilder
{
    private 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++) {
            String result = inst.buildString(Integer.parseInt(argv[i]));
            System.out.println("Constructed string of length " +
                result.length());
        }
    }
}
**************************************

猜你喜欢

转载自can-do.iteye.com/blog/2250708
今日推荐