您的位置:首页 > 其它

JVM之字节码——字节码增强应用(一)_kenvifire-ChinaUnix博客

2012-09-17 17:58 239 查看
前面讲过了字节码增强的一些类库,接下来,我们在这些类库的基础上实现一些具体的应用,主要都是基于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 这样就可以获取到方法的执行时间了,再加上一下统计的功能就可以实现性能分析的功能了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  应用 增强 字节