前面讲过了字节码增强的一些类库,接下来,我们在这些类库的基础上实现一些具体的应用,主要都是基于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;
- }
-
- }
我们修改原来的方法test为test$Impl,把原来的test方法里添加上时间统计和对test$Impl的功能。知道了想要改成什么样子,那么代码就很好实现了。具体代码如下:
- 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);
-
-
- }
我们通过一个modifyMethod方法来对要统计的方法进行修改,它实现的功能如下
1、通过CtNewMethod. copy复制原来的方法
2、把原来的方法重命名为以"$Impl"结尾的方法
3、修改复制的方法的方法体,加入时间统计的代码
上面代码里有个地方需要注意的就是要对返回值进行处理,如果原来的方法有返回值就要先记录下来,并在最后返回,如果没有则不用。
最后,运行我们的代码,结果如下:
Hello.test()time used:1015
这样就可以获取到方法的执行时间了,再加上一下统计的功能就可以实现性能分析的功能了。
阅读(12315) | 评论(0) | 转发(2) |