java Instrument修改位元組碼實現aop功能

來源:互聯網
上載者:User

標籤:pen   tcl   rac   安全   dem   jar   cat   setname   declared   

 

Agent工程2個類:

public class MyAgent {         /**     * 該方法在main方法之前運行,與main方法運行在同一個JVM中     * 並被同一個System ClassLoader裝載     * 被統一的安全性原則(security policy)和上下文(context)管理     */    public static void premain(String agentOps, Instrumentation inst) {        System.out.println("=========premain方法執行========");        System.out.println(agentOps);        // 添加Transformer        inst.addTransformer(new MyTransformer());    }    /**     * 如果不存在 premain(String agentOps, Instrumentation inst)      * 則會執行 premain(String agentOps)     */    public static void premain(String agentOps) {        System.out.println("=========premain方法執行2========");        System.out.println(agentOps);    }}
public class MyTransformer implements ClassFileTransformer {    final static String prefix = "\nlong startTime = System.currentTimeMillis();\n";    final static String postfix = "\nlong endTime = System.currentTimeMillis();\n";    // 被處理的方法列表    final static Map<String, List<String>> methodMap = new HashMap<String, List<String>>();    public MyTransformer() {        add("com.hwtest.demo.MyProgram.sayHello");        add("com.hwtest.demo.MyProgram.sayHello2");    }    private void add(String methodString) {        String className = methodString.substring(0, methodString.lastIndexOf("."));        String methodName = methodString.substring(methodString.lastIndexOf(".") + 1);        List<String> list = methodMap.get(className);        if (list == null) {            list = new ArrayList<String>();            methodMap.put(className, list);        }        list.add(methodName);    }    @Override    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,            ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {        className = className.replace("/", ".");        if (methodMap.containsKey(className)) {// 判斷載入的class的包路徑是不是需要監控的類            CtClass ctclass = null;            try {                ctclass = ClassPool.getDefault().get(className);// 使用全稱,用於取得位元組碼類<使用javassist>                for (String methodName : methodMap.get(className)) {                    String outputStr = "\nSystem.out.println(\"this method " + methodName                            + " cost:\" +(endTime - startTime) +\"ms.\");";                    CtMethod ctmethod = ctclass.getDeclaredMethod(methodName);// 得到這方法執行個體                    String newMethodName = methodName + "$old";// 新定義一個方法叫做比如sayHello$old                    ctmethod.setName(newMethodName);// 將原來的方法名字修改                    // 建立新的方法,複製原來的方法,名字為原來的名字                    CtMethod newMethod = CtNewMethod.copy(ctmethod, methodName, ctclass, null);                    // 構建新的方法體                    StringBuilder bodyStr = new StringBuilder();                    bodyStr.append("{");                    bodyStr.append(prefix);                    bodyStr.append(newMethodName + "($$);\n");// 調用原有代碼,類似於method();($$)表示所有的參數                    bodyStr.append(postfix);                    bodyStr.append(outputStr);                    bodyStr.append("}");                    newMethod.setBody(bodyStr.toString());// 替換新方法                    ctclass.addMethod(newMethod);// 增加新方法                }                return ctclass.toBytecode();            } catch (Exception e) {                System.out.println(e.getMessage());                e.printStackTrace();            }        }        return null;    }}

原始項目:

public class MyProgram {    public static void main(String[] args) {        sayHello();        sayHello2("hello world222222222");    }        public static void sayHello() {        try {            Thread.sleep(2000);            System.out.println("hello world!!");        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public static void sayHello2(String hello) {        try {            Thread.sleep(1000);            System.out.println(hello);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

agent項目打jar包是配置為:

Manifest-Version: 1.0Premain-Class: com.hwtest.MyAgentCan-Redefine-Classes: trueBoot-Class-Path: javassist.jar

cmd執行命令

java -javaagent:MyAgent.jar  -jar MyProgram.jar=========premain方法執行========nullhello world!!this method sayHello cost:2000ms.hello world222222222this method sayHello2 cost:1000ms.

 

 

 

 

地址記錄:

(1)利用ClassFileTransformer實現aop:http://xj84.iteye.com/blog/1221105

(2)Java通過修改類的位元組碼實現aop功能:http://www.360doc.com/content/07/0518/11/25392_506401.shtml

(3)java.lang.instrument動態修改替換類代碼:http://zctya.blog.163.com/blog/static/1209178201131944127774/

java Instrument修改位元組碼實現aop功能

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.