当前位置:网站首页>Agent and classloader

Agent and classloader

2022-06-25 15:20:00 xiao326791055

JavaAgent When was it introduced

JavaAgent yes JDK1.5 Later introduced , It can also be called Java agent

JavaAgent And the order in which our business code is executed ?

JavaAgent Is running on the main Interceptor before method , Its internal method is called premain, That is to say, execute first premain Method , And then execute main Method .

How to run JavaAgent Well ?

Add... To our startup parameters -javaagent:agent-2.0.jar That's all right. .
agent Where does it usually apply , Look at the picture below :
 Insert picture description here

agent Development uses jar What's in the bag

<dependency>    
  <groupId>org.javassist</groupId>    
  <artifactId>javassist</artifactId>    
  <version>3.18.2-GA</version>
</dependency>
<dependency>    
  <groupId>net.bytebuddy</groupId>    
  <artifactId>byte-buddy</artifactId>    
  <version>1.10.19</version>
</dependency>
<dependency>    
  <groupId>net.bytebuddy</groupId>    
  <artifactId>byte-buddy-agent</artifactId>    
  <version>1.10.19</version>
</dependency>

Agent What can be done ?

1、 You can load java Before the file, block and modify the bytecode
2、 The bytecode of the loaded class can be changed at runtime
3、 Get all classes that have been loaded
4、 Get all classes that have been initialized
5、 Get the size of an object
6、 Will be a jar Add to bootstrapclasspath As a high priority bootstrapClassloader load
7、 Will be a jar Add to classpath Internal supply AppClassloard To load the

Agent pack

Mode one 、MANIFEST.MF
1、 stay resources Create under directory META-INF/MANIFEST.MF
2、MANIFEST.MF The following documents are added to the document
3、 Use maven Make jar package
 Insert picture description here Mode two 、Pom.xml
1、pom.xml add plugin, The content is shown in the following screenshot
2、 Use maven Make jar package
 Insert picture description here

Simple agent Of demo

1、 The interception class is named " com.jd.jsf.gd.server.ProviderProxyInvoker” Ending class .
2、 Insert some code before or after the code starts
insertBefore Insert... Before code execution
insertAfter Insert... After code execution
setBody Replace method body

 Insert picture description here

agent Ways to enhance code

Mode one 、 utilize className.endsWith Directional interception class

 Insert picture description here

Mode two 、 utilize ElementMatchers Code interception , Use intercept Intercept
 Insert picture description here
Mode three 、 utilize ElementMatchers Code interception , Use advice enhance
 Insert picture description here

Code enhancement examples

Mode one 、Advice Code example
 Insert picture description here
Mode two 、Intercept Code example
 Insert picture description here

If we were agent Of advice perhaps intercept What happens to the code that calls the business system ?

Execute the following code , What results will we get
 Insert picture description here
We will reap one
Caused by: java.lang.ClassNotFoundException: org.apache.dubbo.rpc.RpcContext

Why? ?

Agent And class loaders

Let's take a look at the familiar parental delegation model
 Insert picture description here

Let's see tomcat Class loader for
 Insert picture description here
To sum up, there are ClassNotFoundException The cause of the abnormality :
Agent The default class loader for is AppClassLoader,
Our code is generally deployed in tomcat Next , therefore
Our class loaders are generally WebAppClassLoader;

So find one to explain why the code on the previous page appears
ClassNotFoundException Why .

reason :
AppClassLoader We can't load our business code

Agent Class and business class loader solutions

1、 Custom class loaders , Inherit URLClassLoader
2、 rewrite loadClass, Try to load it yourself first , If it cannot be loaded by itself, it will be handed over to the parent class loader
3、 Specify the parent class loader for custom class loading ( Class loader for business code ,advice perhaps intercept The business class can be loaded )
4、 Designated us agent The plug-in address of the code ( That is, where the code needs to be enhanced ), adopt URL obtain
5、 When initializing user-defined class loading, the fourth step will be URL Pass in
5、 Use custom class loader loadClass Method to load our plug-in code

The code implementation of the class loader is shown in the following figure :

public class AgentClassLoader extends URLClassLoader {
    

    private final ClassLoader upperClassLoader;

    public AgentClassLoader(URL[] urls, ClassLoader parent) {
    
        super(urls, parent);
        this.upperClassLoader = parent;
    }

    @Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    
        System.out.println("name:"+name+"; Start trying to load ;");
        final Class<?> loadedClass = findLoadedClass(name);
        if (loadedClass != null) {
    
            if (resolve) {
    
                resolveClass(loadedClass);
            }
            return loadedClass;
        }

        //  Priority from parent(SystemClassLoader) Load system classes in , Avoid throwing ClassNotFoundException
        //if (name != null && (name.startsWith("sun.") || name.startsWith("java.") || name.contains("com.jd.car.log.plugins"))) {
    
// if (name != null && (name.startsWith("sun.") || name.startsWith("java.") || name.contains("com.jd.car.log.plugins"))) {
    
// System.out.println("super Start trying to load :"+ super.toString() +" ;name:"+name +";super The parent loader of :"+super.getParent());
// return super.loadClass(name, resolve);
// }
// System.out.println(" Start trying to load the parent loader ;upperClassLoader Parent loader :"+upperClassLoader.getParent());
// return Class.forName(name, true, upperClassLoader);
        System.out.println("super Start trying to load :"+ super.toString() +" ;name:"+name +";super The parent loader of :"+super.getParent());
        return super.loadClass(name, resolve);
    }
}

Intercept The code implementation is shown in the figure below :

public class MvcInterceptor {
    
    AgentClassLoader agentClassLoader;

    public MvcInterceptor(ClassLoader classLoader) {
    

        try {
    
            URL agentJarUrl = new File("/export/carAgent/carLogPlugin-1.0.jar").toURI().toURL();
            System.out.println("Linux Next address :"+agentJarUrl);
            agentClassLoader = new AgentClassLoader(new URL[]{
    
                    agentJarUrl
            }, classLoader);
            System.out.println(" Class loader created successfully ;agentClassLoader Class loader for :" + agentClassLoader
                    + ";agentClassLoader Parent loader :" + agentClassLoader.getParent());
            Class<?> clazz = agentClassLoader.loadClass("com.jd.car.log.plugins.spring.MvcMethodInterceptor", true);
            System.out.println("Class<?> clazz Class loader for " + clazz.getClassLoader());
            Object plugin = clazz.newInstance();

        } catch (Exception e) {
    
            e.printStackTrace();
        }
    }


    @RuntimeType
    public Object intercept(@This Object obj, @Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> callable) throws Exception {
    
        Class<?> clazz = agentClassLoader.loadClass("com.jd.car.log.plugins.spring.MvcMethodInterceptor", true);
        Object plugin = clazz.newInstance();

        Object before = plugin.getClass().getMethod("before", Object.class).invoke(plugin, obj);
        try {
    
            return callable.call();
        } finally {
    
            plugin.getClass().getMethod("after", Object.class).invoke(plugin, before);
        }
    }

Think and reflect

Question 1 、 Whether the classloader we just customized conforms to the parental delegation model ?
Do not conform to the , Because we first try to load by ourselves , Then it is handed over to the parent class loader to load

Question two 、Tomcat Does the classloader conform to the parental delegation model ?
Do not conform to the , Every webappClassLoader Load... In your own directory class file , Will not be passed to the parent loader

原网站

版权声明
本文为[xiao326791055]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202200504232433.html