前面講過了字節碼增強的一些類庫,接下來,我們在這些類庫的基礎上實現一些具體的應用,主要都是基於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 這樣就可以獲取到方法的執行時間了,再加上一下統計的功能就可以實現性能分析的功能了。