Introduction of Instrumentation
Java probe technology, with Instrumentation, developers can build an application-independent Agent to monitor and assist programs running on the JVM, and even replace and modify the definition of some classes without intruding on business code
Mature application
APM (Application Performance Management) tools in the Java field are almost implemented based on Instrumentation.
- Zipkin: Twitter’s open-source distributed tracking tool, integrated with Spring Cloud Sleuth, is widely used and stable
- Skywalking: A distributed tracking, analysis, and alarm tool developed by Huawei. It is now an open source project of Apache
- Cat: A distributed link tracking tool developed by Dianping.
Arthas is an open source Java diagnostic tool for Alibaba based on this.
So many excellent products are using Java probe Instrumentation, are you interested in understanding it.
Using the process
Import proxy class
Execute before the main method
public class MyAgent {
static Instrumentation instrumentation;
public static void premain(String agentArgs, Instrumentation inst)
throws Exception {
try {
instrumentation = inst;
inst.addTransformer(new MyClassFileTransformer());
} catch (Exception e) {
}
}
}
Copy the code
You need to provide one of the following two methods, if two, the first one has the higher priority
public static void premain(String agentOps, Instrumentation instrumentation);
public static void premain(String agentOps);
Copy the code
Custom ClassFileTransformer
package top.soft1010.java.myagent; import javassist.*; import javassist.expr.ExprEditor; import javassist.expr.MethodCall; import javassist.scopedpool.ScopedClassPool; import javassist.scopedpool.ScopedClassPoolRepositoryImpl; import java.io.IOException; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; /** * Created by bjzhangjifu on 2021/9/27. */ public class MyClassFileTransformer implements ClassFileTransformer { @Override public byte[] transform(ClassLoader loader, String className, Class<? > classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.out.println("Transforming " + className); // Return if (! className.startsWith("top/soft1010")) { return classfileBuffer; If (loader == null) {return classfileBuffer; if (loader == null) {return classfileBuffer; } try { // if (className ! = null && className.indexOf("/") ! = -1) { // className = className.replaceAll("/", "."); // } CtClass ctClass = ClassPool.getDefault().makeClass(new java.io.ByteArrayInputStream(classfileBuffer)); CtMethod[] methods = ctClass.getDeclaredMethods(); for (CtMethod method : methods) { try { method.insertAfter("System.out.println("--after--");" ); method.insertBefore("System.out.println("--before--");" ); } catch (CannotCompileException e) { e.printStackTrace(); } } return ctClass.toBytecode(); } catch (Exception e) { e.printStackTrace(); } return classfileBuffer; }}Copy the code
ClassFileTransformer is used to modify the class file before the JVM loads the class. It has only one transform method, which can be implemented to modify the class bytecode (using Javassist, ASM, etc.) and return the modified class bytecode, with two caveats:
- If this method returns NULL, we return the class without processing it. Otherwise, the original class is replaced by the byte[] we return
- Instrumentation#addTransformer(ClassFileTransformer)
- When more than one Transformer exists, the byte array returned by one Transformer call becomes the input for the next Transformer call
run
Here we’ll just write a main method class, or a JAR
public class MyTest { public static void main(String[] args) { new MyTest().test(); } private void test() { System.out.println(" ----- test ----- "); }}Copy the code
Execute the command
java -javaagent:myagent.jar top.soft1010.java.myagent.MyTest
Copy the code
The interview
1. Modify the bytecode when loading the class?
Yes, using a Java probe, JavaAgent. JavaAgent was introduced after JDK 1.5 and can also be called a Java agent. JavaAgent is an interceptor that runs before main. Its built-in method is called Premain, which means that the premain method is executed first and then main. The premain method has an Instrumentation parameter, with which we can add a custom FileTransformer. This interface has only one method, transform. With this method we can get the bytecode of the loaded class, of course we can also modify the bytecode. For example, add monitoring information before and after the methods of the specified class.Copy the code
2. Discuss the application of Java probe technology javaAgent
Skywalking: A distributed tracking, analysis and alarm tool developed by Wu Sheng (Huawei), is now a distributed link tracking tool developed by Cat: Dianping, an open source project owned by Apache. Arthas: A Java diagnostics tool that is open source for Ali and of course many large companies have their own custom APM tools based on this as wellCopy the code
The source code
The source code involved in the article