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

Source: Internet
Author: User

A more common method of AOP is to dynamically generate a subclass for the original class. The method of calling the subclass overwrites the parent class to implement the function of AOP. The famous Hibernate and Spring frameworks use this technology to implement the "lossless injection" of AOP ".
 
Next, we will use an example to calculate the time statistics before and after the dynamic injection method is executed when you call foo.exe cute.

[Java]
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 static 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 use time:" + (end-start ));
}
}
 
Public static void main (String [] args) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, 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); // use execute to modify the content of the method.


// Gets the bytecode of the Example class, and loads it dynamically
 
FileOutputStream fos = new FileOutputStream ("e: \ logs \ Example. class ");
Fos. write (code );
Fos. close ();
}

Static class MethodChangeClassAdapter extends ClassVisitor implements Opcodes {
 
Public MethodChangeClassAdapter (final ClassVisitor cv ){
Super (Opcodes. ASM4, cv );
}
 
@ Override
Public MethodVisitor visitMethod (
Int access,
String name,
String desc,
String signature,
String [] exceptions)
{
If ("execute". equals (name) // execute here is the method to be modified.
{
MethodVisitor mv = cv. visitMethod (access, name, desc, signature, exceptions); // obtain the original method first.
MethodVisitor newMethod = null;
NewMethod = new AsmMethodVisit (mv); // access the method 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 only once when the method's header is accessed
VisitMethodInsn (Opcodes. INVOKESTATIC, Monitor. class. getName (), "start", "() V ");
Super. visitCode ();

}

@ Override
Public void visitInsn (int opcode ){
// This method can obtain the operation type of each instruction in the method, which is accessed multiple times
// If a new instruction should be added at the end of the method, It should be judged:
If (opcode = Opcodes. RETURN)
{
VisitMethodInsn (Opcodes. INVOKESTATIC, Monitor. class. getName (), "end", "() V ");
}
Super. visitInsn (opcode );
}

}
 
}

Output:
[Java]
Public static void AsmAopExample$Foo.exe cute ()
Public native int java. lang. Object. hashCode ()
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 ()
Public final native void java. lang. Object. Policy ()
Public final native void java. lang. Object. policyall ()
Test changed method name
Execute method use time: 10

We can see that sleep is 10 ms in the execute method, and the print is 10 ms. Here we call monitor before executing the execute method. start () method. The method returns the end method of monitor to achieve the statistical function. However, this is just an example. to count the execution time of each method, during statistics concurrency, the method statistics must be expanded here, but the idea is similar.
 
 
We can check the final generated Foo class file through the reflected source code:

[Java]
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 ();
}
}
Author: zhongweijian

Related Article

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.