A preliminary study of javaagent

    In the process of business development, it is often necessary to use maven to package the code into a jar package to run on the server. But during the packaging process, maven will put all the dependencies into the package, no matter some recursive dependencies are unnecessary, although we can use the mvn dependence:tree command to get all the dependency graphs, and then pass them in the pom.xml file. The label for exclusion will remove dependencies, but this method first requires a lot of manual verification, and second, it cannot accurately find unnecessary dependent files. Most of them need to rely on intuition, so it will waste a lot of time. Here In this case, prepare to be a JVM-level tool. By monitoring the process of loading classes into JVM, you can get all the required classes, so as to accurately compress the jar package.
    Returning to the topic, after determining the requirements and general ideas, in the process of preparation, we found a javaagent that can effectively fulfill our requirements.
What is javaagent?
    As the name suggests, javaagent is something that acts as an agent for java. Find a description that I think is more accurate
quote
javaagent is a way to modify bytecode without affecting normal compilation. As a strongly typed language, Java cannot generate jar packages without compiling. With javaagent technology, classes and methods can be modified at the bytecode level. At the same time, javaagent can also be understood as a way of code injection. But this injection is more beautiful than spring's aop.

    After my simple operation, my understanding of this thing is that it is a class enhancer at the bytecode level, that is, it can add some functions that we need to add without changing the class.
How to use javaagnet, there are two conditions, first, implement a premain method, and second, when packaging, clearly implement the class that implements the premain method.
    After packaging the custom agent, you can see that the content of the jar package is
Manifest-Version: 1.0
Premain-Class: ClassAgent
Built-By: .
Created-By: Apache Maven 3.5.0
Build-Jdk: 1.8.0_111

    That is, there is a class with a specified preclass, which can be used as a toolkit for javaagent.
The specific method of use is, when executing our code, add -javaagent:{path-to-our-agent.jar} to the startup parameter, and replace it with the address of our agent toolkit, so that we can see the execution Before the real code, our premain method is executed first, which is why it is called pre-main ^-^

    Too late, I just wrote a demo to experiment.
   
public class ClassAgent {
    public static void premain(String agentOps, Instrumentation instrumentation) {
        System.out.println("---------start agent-------------");
        System.out.println(agentOps);
        instrumentation.addTransformer(new ClassTransformer());
    }
}

public class ClassTransformer implements ClassFileTransformer {
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        public class ClassTransformer implements ClassFileTransformer {
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        System.out.println(className.replace('/','.'));
        return new byte[0];
    }
}
        return new byte[0];
    }
}

Then register the premain class in the pom.xml file
<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Premain-Class>ClassAgent</Premain-Class>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

Finally, package the project, pass the location of the jar package as a parameter, pass it into the startup parameters of the actual code execution, and start it.
See console output

. A small step forward from the goal, go to sleep

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326098363&siteId=291194637