Java.lang.Instrument Proxy Agent Use detailed introduction _java

Source: Internet
Author: User
Tags aop jboss

Java.lang.Instrument Proxy Agent uses

The Java.lang.Instrument package was introduced in JDK5, and the programmer dynamically modifies the class code by modifying the bytecode of the method. This is typically done before the class's Main method invocation, which is implemented by specifying a proxy class for the class in Java. Invoking the Classfiletransformer transform method before the bytecode of the class is loaded into the JVM, enabling the ability to modify the methods of the original class to implement AOP, the benefit of which is that it does not produce a new class like the dynamic proxy or the Cglib technology that implements AOP. There is no need for the original class to have an interface.

(1) a proxy (agent) is an interceptor (interceptor) before your main method, which is the code that executes the agent before the main method executes. The code for the agent runs in the same JVM as your main method, and is loaded by the same system ClassLoader, managed by the same security policy (secure policy) and context. Proxy (agent) the name is a little misleading ingredient, it is not the same as our general understanding of the agent. Java agents are easier to use. How do I write a Java agent? Simply implement Premain this method: public static void Premain (String Agentargs, Instrumentation Inst) JDK 6, if the definition of this premain above is not found, You will also try to invoke the following Premain definition: public static void Premain (String Agentargs)

(2) The Agent class must be typed into a jar bag, and then inside the meta-inf/mainifest. MF, must contain premain-class this property. Here is an example of a MANIFEST.MF:

manifest-version:1.0 Premain-class:myagent1 created-by:1.6.0_06

Then add the MANIFEST.MF to your jar bag. The following is a list of manifest attributes for the agent jar file: Premain-class If the JVM specifies a proxy when it is started, this property specifies the proxy class, which is the class that contains the Premain method. This property is required if the JVM specifies a proxy when it is started. If the property does not exist, then the JVM aborts. Note: This property is a class name, not a filename or path. Agent-class If you implement a mechanism that supports the initiation of a proxy at some point after the VM is started, this property specifies the proxy class. The class that contains the Agentmain method. This property is required and the agent will not start if it does not exist. Note: This is the class name, not the file name or path. Boot-class-path sets the path list for the Boot class loader search. A path represents a directory or library (often referenced as a JAR or zip library on many platforms). After a platform-specific mechanism for finding a class fails, the boot class loader searches for these paths. Search for paths in the order listed. The path in the list is separated by one or more spaces. Path component syntax using a hierarchical URI. If the path starts with a slash character ("/"), it is an absolute path, otherwise the relative path. The relative path is resolved according to the absolute path of the agent JAR file. Ignores incorrectly formatted paths and nonexistent paths. If the agent was started at some point after the VM was started, the path that does not represent the JAR file is ignored. This property is optional. The Can-redefine-classes Boolean value (TRUE or FALSE, regardless of case). Whether the required classes for this agent can be redefined. Values other than true are treated as false. This property is optional and the default value is False. The Can-retransform-classes Boolean value (TRUE or FALSE, regardless of case). Whether the classes required for this agent can be converted. Values other than true are treated as false. This property is optional and the default value is False. The Can-set-native-method-prefix Boolean value (TRUE or FALSE, regardless of case). Whether you can set the native method prefix required by this agent. Values other than true are treated as false. This property is optional and the default value is False.

(3) All of these agent jar packages will automatically be added to the classpath of the program. So there's no need to manually add them to the classpath. Unless you want to specify the order of Classpath.

(4) The number of-javaagent this parameter in a Java program is unrestricted, so you can add as many Java agents as you want. All Java agents are executed in the order you define them. For example:

Java-javaagent:myagent1.jar-javaagent:myagent2.jar-jar Myprogram.jar

Suppose the main function inside the Myprogram.jar is in the MyProgram. Myagent1.jar, Myagent2.jar, the Premain classes implemented in these 2 jar packages are MyAgent1, and the order in which the MyAgent2 programs are executed will be:

Myagent1.premain-> myagent2.premain-> myprogram.main

(5) In addition, the premain that is placed after the main function is not executed, for example:

Java-javaagent:myagent1.jar-jar Myprogram.jar-javaagent:myagent2.jar

MyAgent2 are placed behind the Myprogram.jar, so the premain of the MyAgent2 will not be executed, so the result of the execution would be:

Myagent1.premain-> Myprogram.main

(6) Each Java agent can receive a string-type parameter, the Agentargs in Premain, which is defined by the Java option. For example:

Java-javaagent:myagent2.jar=thisisagentargs-jar Myprogram.jar

The value of Premain received Agentargs in MyAgent2 will be "Thisisagentargs" (excluding double quotes).

(7) instrumentation in the parameter: through the instrumentation inst in the parameter, add the classfiletransformer of your definition to change the class file. The custom transformer here implements the Transform method, which provides a way to modify the bytecode of the class that is actually being executed, or even to execute another class method. For example: Write the Agent class:

Package Org.toy;
Import java.lang.instrument.Instrumentation;
Import Java.lang.instrument.ClassFileTransformer;
public class Perfmonagent {
  private static instrumentation Inst = null;
  /**
   * This was called before the application ' Main-method is called, * when this agent was specified to the
   Java VM.
   **/public
  static void Premain (String Agentargs, instrumentation _inst) {
    System.out.println (" Perfmonagent.premain () was called. ");
    Initialize The static variables we use to track information.
    Inst = _inst;
    Set up the class-file transformer.
    Classfiletransformer trans = new Perfmonxformer ();
    System.out.println ("Adding a Perfmonxformer instance to the JVM.");
    Inst.addtransformer (trans);
  }


write Classfiletransformer class:


Package Org.toy;
Import Java.lang.instrument.ClassFileTransformer;
Import java.lang.instrument.IllegalClassFormatException;
Import Java.security.ProtectionDomain; Import Javassist.
Cannotcompileexception; Import Javassist.
Classpool; Import Javassist.
Ctbehavior; Import Javassist.
Ctclass; Import Javassist.
Notfoundexception;
Import Javassist.expr.ExprEditor;
Import Javassist.expr.MethodCall; public class Perfmonxformer implements Classfiletransformer {public byte[] transform (ClassLoader loader, String Classna Me, class<?> classbeingredefined, Protectiondomain protectiondomain, byte[] classfilebuffer) throws
    illegalclassformatexception {byte[] transformed = NULL;
    System.out.println ("Transforming" + className);
    Classpool pool = Classpool.getdefault ();
    Ctclass cl = null;
      try {cl = Pool.makeclass (New Java.io.ByteArrayInputStream (Classfilebuffer));
 if (cl.isinterface () = = False) {ctbehavior[] methods = Cl.getdeclaredbehaviors ();       for (int i = 0; i < methods.length i++) {if (Methods[i].isempty () = False) {Domethod (M
          Ethods[i]);
      } transformed = Cl.tobytecode (); The catch (Exception e) {System.err.println ("could not instrument" + className +), Exception: "+
    E.getmessage ());
      finally {if (CL!= null) {Cl.detach ();
  } return transformed; private void Domethod (Ctbehavior method) throws Notfoundexception, cannotcompileexception {//Method.insert
    Before ("Long stime = System.nanotime ();");
    Method.insertafter ("System.out.println" ("Leave" +method.getname () + "and time:\" + (System.nanotime ()-stime)); Method.instrument (New Expreditor () {public void edit (Methodcall m) throws Cannotcompileexception {M.replac E ("{Long stime = System.nanotime (); $_ = $proceed ($$); System.out.println (\ "" + m.getclassname () + ".")
              +m.getmethodname ()  + ": \" + (System.nanotime ()-stime));
  }
    });

 }
}

The above two classes are the core of the agent, and the JVM starts and invokes Perfmonagent.premain before the application loads, and then instantiates a custom classfiletransforme in Perfmonagent.premain Perfmonxformer, and through Inst.addtransformer (trans), add the Perfmonxformer instance to the instrumentation instance (passed by the JVM), so that when the class in the application loads, Perfmonxformer.transform will be called, you can change the loaded class in this method, it is really a bit magical, in order to change the byte code of the class, I use the JBoss javassist, although you don't have to use it, But JBoss's javassist is really powerful and makes it easy for you to change the byte code of the class.

In the above method I added a long stime = System.nanotime () to the method entry of each class by changing the byte code of the class, and in the method's exit joined the SYSTEM.OUT.PRINTLN (" Methodclassname.methodname: "+ (System.nanotime ()-stime));

Thank you for reading, I hope to help you, thank you for your support for this site!

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.