Use ASM4.0 to implement AOP functionality and monitor the execution time of each method __AOP

Source: Internet
Author: User
Tags aop

The previous blog http://zhwj184.iteye.com/admin/blogs/1630756 An example of ASM usage, this time using ASM to dynamically count the execution times of each method to achieve AOP functionality.

A more general approach to AOP is to dynamically generate subclasses of the original class, and to invoke the subclass's methods to overwrite the parent class to implement the AOP functionality. The famous Hibernate and Spring framework is the use of this technology to achieve the "lossless injection" of AOP.

Here we will use an example to statistic the execution time of the method before and after the dynamic injection method Foo.execute the call


Import Java.io.FileOutputStream;
Import java.io.IOException;
Import java.lang.reflect.InvocationTargetException;

Import Java.lang.reflect.Method;
Import Org.objectweb.asm.ClassReader;
Import Org.objectweb.asm.ClassVisitor;
Import Org.objectweb.asm.ClassWriter;
Import Org.objectweb.asm.MethodVisitor;

Import Org.objectweb.asm.Opcodes; public class Asmaopexample extends ClassLoader implements opcodes{public static class Foo {public stat
            IC void Execute () {System.out.println ("Test changed method name");
            try {thread.sleep (10); 
            catch (Interruptedexception e) {//TODO auto-generated catch block E.printstacktrace ();
        
        }} public static class monitor{static long start = 0;
        public static void Start () {start = System.currenttimemillis (); public static void End () {Long end = System. Currenttimemillis ();
        System.out.println ("Execute Method with Time:" + (End-start)); } public static void Main (string[] args) throws IOException, IllegalArgumentException, SecurityException, Illeg
        Alaccessexception, invocationtargetexception {classreader cr = new Classreader (Foo.class.getName ());
        Classwriter cw = new Classwriter (CR, CLASSWRITER.COMPUTE_MAXS);
        Classvisitor CV = new Methodchangeclassadapter (CW);

        Cr.accept (CV, OPCODES.ASM4);


        Gets the bytecode of the Example class, and loads it dynamically byte[] code = Cw.tobytearray ();
        Asmaopexample loader = new Asmaopexample ();

        class<?> ExampleClass = Loader.defineclass (Foo.class.getName (), code, 0, Code.length);
        For [Method Method:exampleClass.getMethods ()] {System.out.println (method);  } exampleclass.getmethods () [0].invoke (null, NULL);
        
        
Adjust execute, modify method content        Gets the bytecode of the Example class, and loads it dynamically fileoutputstream fos = new Fileoutput
        Stream ("E:\\logs\\example.class");
        Fos.write (code);
    Fos.close (); Static class Methodchangeclassadapter extends Classvisitor implements opcodes {public Methodchangecla
        Ssadapter (Final classvisitor CV) {super (OPCODES.ASM4, CV);
            @Override public methodvisitor visitmethod (int access, String name, String desc, string signature, string[] exceptions) {if ("Execute". Equals (NA  ME)//Here Execute is the method that needs to be modified, modify the method content {Methodvisitor mv = Cv.visitmethod (access, name, DESC,  
                Signature, exceptions)//First get the original method methodvisitor Newmethod = null; Newmethod = new Asmmethodvisit (MV);  
            Access the method that needs to be modified return newmethod;  
            
       }     return null; } static class Asmmethodvisit extends Methodvisitor {public asmmethodvisit (methodvisitor MV)    
        {Super (OPCODES.ASM4, MV); @Override public void Visitcode () {//This method is accessed at the head of the method, accessed only once VI 
            SITMETHODINSN (Opcodes.invokestatic, Monitor.class.getName (), "Start", "() V");
            
        Super.visitcode ();
            @Override public void visitinsn (int opcode) {//This method can get the action type of each instruction in the method, accessed multiple times If you should add a new instruction at the end of the method, you should decide: if (opcode = = Opcodes.return) {VISITMETHODINSN (OpCo Des. 
            Invokestatic, Monitor.class.getName (), "End", "() V");
        } super.visitinsn (opcode);
 }  
        
    }

}

Output:

public static void Asmaopexample$foo.execute () public
native int Java.lang.Object.hashCode () is public
final Native Java.lang.Class Java.lang.Object.getClass () public
final void java.lang.Object.wait (Long,int) throws Java.lang.InterruptedException public
final void java.lang.Object.wait () throws Java.lang.InterruptedException Public
final native void Java.lang.Object.wait (long) throws Java.lang.InterruptedException public
Boolean Java.lang.Object.equals (java.lang.Object) public
java.lang.String java.lang.Object.toString ()
Final native void Java.lang.Object.notify () public
final native void Java.lang.Object.notifyAll ()
test changed Method name
execute to use Time:10

You can see the 10ms in the Execute method, which is also printed here 10ms, where the Monitor.start () method is called before the Execute method executes, and the method return is to call the end method of the monitor to achieve the statistical function. But here is just an example, if you want to count the execution time of each method, the statistics of concurrent methods will certainly be extended here, but that's almost the way it is.

Let's look at the final generated class file of Foo classes through the reflected source code:

Import Java.io.PrintStream;

public class Asmaopexample$foo
{public
  static void execute ()
  {
    AsmAopExample.Monitor.start (); SYSTEM.OUT.PRINTLN ("Test changed method name");
    try {
      thread.sleep (10L);
    }
    catch (Interruptedexception e) {
      e.printstacktrace ();
    }
    AsmAopExample.Monitor.end ();
  }


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.