JVM之字節碼——字節碼增強應用(一)_kenvifire-ChinaUnix博客

前面講過了字節碼增強的一些類庫,接下來,我們在這些類庫的基礎上實現一些具體的應用,主要都是基於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 這樣就可以獲取到方法的執行時間了,再加上一下統計的功能就可以實現性能分析的功能了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章