Java implements AOP functionality by modifying the byte code of a class

Source: Internet
Author: User
Tags aop
In the jdk5.0 version, a new interface java.lang.instrument.Instrumentation is added, which can be used to modify the byte code of the class when the class is loaded, and to change the implementation of the function of the class. In this way, we can implement the functions of AOP, which is another kind of AOP implementation different from proxy dynamic proxy.
The principle of this method is very simple, that is, by modifying the compiler has compiled the bytecode to modify the class, and we usually modify the class source to implement the class changes almost. It's just a modification at two different levels.
This is the specific way to use this interface.
First step:
You need to implement the Java.lang.instrument.Instrumentation interface by modifying the byte code of the class while loading the class in the implementation class of this interface. The following is the implementation of the interface Transformer.java
public class Transformer implements Classfiletransformer {
Methods that are called by the JVM before the program is run
public static void Premain (String args, instrumentation inst) {
Inst.addtransformer (New Transformer ());
}
Public byte[] Transform (ClassLoader loader, String className,
Class<?> classbeingredefined, Protectiondomain Protectiondomain,
Byte[] classfilebuffer) throws Illegalclassformatexception {
Byte[] result =null; Defining a new byte-code storage variable
This changes the class by modifying the byte code Classfilebuffer of the class.
return result; Returns the new byte code
}
}
Step Two:
You need to generate a jar file, such as T.jar, to add Premain-class:transformer to the MANIFEST.MF of the jar file for the class file of Transformer classes. When you run the program, you need to use the following parameter-javaagent:t.jar in the JVM. This way, when the JVM is running, it first finds the Premain method of the Transformer class specified by Premain-class:transformer. It also implements the ability to modify the byte code of a class in the future loading of classes.

Is the method of using the Java.lang.instrument.Instrumentation interface. So how do you implement AOP functionality, which requires the ability to add AOP to the functionality of the class when you change the bytecode.
Now let's look at how to implement the AOP feature that prints the current time before and when the method is called.
Change the transform method of transformer first
Public byte[] Transform (ClassLoader loader, String className,
Class<?> classbeingredefined, Protectiondomain Protectiondomain,
Byte[] classfilebuffer) throws Illegalclassformatexception {
Byte[] result = Classfilebuffer; Defining a new byte-code storage variable
This changes the class by modifying the byte code Classfilebuffer of the class.
if (loader!= classloader.getsystemclassloader ()) {
return classfilebuffer;
}

Classreader reader = new Classreader (classfilebuffer);
Classwriter writer = new Classwriter (true);
Classadapter adapter = new Perfclassadapter (writer, className);
Reader.accept (adapter, true);
result = Writer.tobytearray ();
return result; Returns the new byte code
}

This modifies the byte code by Perfclassadapter the class.
Perfclassadapter.java
public class Perfclassadapter extends Classadapter {
Private String ClassName;
Public Perfclassadapter (Classvisitor visitor, String Theclass) {
Super (visitor);
This.classname = Theclass;
}
Public methodvisitor visitmethod (int arg,
String name,
String Descriptor,
String Signature,
String[] Exceptions) {
Methodvisitor mv = Super.visitmethod (ARG,
Name
Descriptor,
Signature
exceptions);
Methodadapter ma = new Perfmethodadapter (mv, ClassName, name);
Return MA;
}
}
Perfmethodadapter.java
public class Perfmethodadapter extends Methodadapter {
Private String _classname, _methodname;

Public Perfmethodadapter (Methodvisitor visitor,
String ClassName,
String methodname) {
Super (visitor);
_classname = ClassName;
_methodname = methodname;
}

public void Visitcode () {
THIS.VISITLDCINSN (_classname);
THIS.VISITLDCINSN (_methodname);
THIS.VISITMETHODINSN (Invokestatic,
"Aop_log",
"Start",
"(ljava/lang/string; ljava/lang/string) V ");
Super.visitcode ();
}

public void visitinsn (int inst) {
Switch (inst) {
Case Opcodes.areturn:
Case Opcodes.dreturn:
Case Opcodes.freturn:
Case Opcodes.ireturn:
Case Opcodes.lreturn:
Case Opcodes.return:
Case Opcodes.athrow:
THIS.VISITLDCINSN (_classname);
THIS.VISITLDCINSN (_methodname);
THIS.VISITMETHODINSN (Invokestatic,
"Aop_log",
"End",
"(ljava/lang/string; ljava/lang/string) V ");
Break
Default
Break
}
SUPER.VISITINSN (inst);
}
}
Aop_log.java
public class Aop_log {

public static void Start (String className, String methodname) {
System.out.println (New StringBuilder (ClassName)
. Append ('/t ')
. Append (methodname)
. Append ("/tstart/t")
. Append (System.currenttimemillis ());
}
public static void End (String className, String methodname) {
System.out.println (New StringBuilder (ClassName)
. Append ('/t ')
. Append (methodname)
. Append ("/tend/t")
. Append (System.currenttimemillis ());
}
}
Together, these classes implement the Start method of the Aop_log class before calling the method, and call the end method of the Aop_log class after the method returns.

Now write a test class to test.
Tsmain.java
public class Tsmain {

public static void Main (string[] args) {
Tsmain TSM = new Tsmain ();
Tsm.printclassname ();
}

public void Printclassname () {
System.out.println ("Hello" +this.getclass (). GetName ());
}
}

Run the command as follows:
=>java-javaagent:t.jar classpath cpdir Tsmain # Cpdir The path of the class to be used

The output results are as follows:
Tsmain Main start 1179374205562
Tsmain <init> Start 1179374205562
Tsmain <init> End 1179374205562
Tsmain printclassname Start 1179374205562
Hello Tsmain
Tsmain Printclassname End 1179374205562
Tsmain Main End 1179374205562


This completes the functionality of the entire AOP implementation. It is necessary to add that the bytecode for modifying the class is using the ASM's underlying class library, so you need to import these ASM jar files.

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.