前面讲过了字节码增强的一些类库,接下来,我们在这些类库的基础上实现一些具体的应用,主要都是基于Javassist的应用。
1、性能测试 在一些特殊的场景下,我们需要对代码的性能进行统计,以发现耗费时间最长的地方,然后对代码进行优化。或者说是我们需要统计所有方法的执行时间和次数,看哪个方法的执行时间和次数最多。这里我们借助Javassist来实现这样的一个功能。当然,我们功能比较简单,只要给每个方法添加上输出执行时间的功能,具体的数据统计就不做了。 实现的方式很简单,在每个方法的开始和结束的地方分别计时,然后计算出时间差即可。 例如,我们有一个Hello.java类
点击(此处)折叠或打开
-
public class Hello {
public String test() throws Exception{
Thread.currentThread ().sleep(1000);
return "test";
}
}
点击(此处)折叠或打开
-
public class Hello {
public String test$Impl() throws Exception{
return "test";
}
public String test( ) throws Exception{
long start = System.currentTimeMillis();//统计开始时间
Object result = test$Impl();//调用原方法
long end = System.currentTimeMillis();//统计结束时间
System.out.println("method test time used:" (end - start));//计算时间
return result;
}
}
点击(此处)折叠或打开
-
public static void modifyMethod(CtMethod method,CtClass clazz) throws Exception{
//从原方法复制产生一个新的方法
CtMethod newMethod = CtNewMethod. copy(method, clazz, null);
//重命名原方法
String methodName = method.getLongName();
String oldName = method.getName() "$Impl";
method.setName(oldName);
StringBuilder body = new StringBuilder();
body.append( "{long start = System.currentTimeMillis();" );
//如果有返回值,则记录返回值,没有则不记录
if(method.getReturnType()==CtClass. voidType){
body.append( oldName "($$);");
} else{
body.append( "Object result = " oldName "($$);" );
}
body.append( " long end = System.currentTimeMillis();"
"System.out.println(\"" methodName "\""
"\"time used:\" " "(end - start));" );
//如果有返回值,则添加return 语句
if(method.getReturnType()==CtClass. voidType){
body.append( "}");
} else{
body.append( "return result;}" );
}
newMethod.setBody(body.toString());
clazz.addMethod(newMethod);
}
最后,运行我们的代码,结果如下: Hello.test()time used:1015 这样就可以获取到方法的执行时间了,再加上一下统计的功能就可以实现性能分析的功能了。