Java Agent-based Full Link Monitoring Three ByteBuddy Operational Monitoring Method Bytecode

Posted by Malkavbug on Wed, 02 Oct 2019 18:45:12 +0200

Chapter list: pay attention to the public address, bugstack wormhole stack, reply to < JavaAgent based full link monitoring > get source code.

  • Java Agent-based full-link monitoring JavaAgent "
  • Java Agent-based Full Link Monitoring II "Increasing Monitoring Execution Time by Bytecode"
  • Java Agent-based Full Link Monitoring Three ByteBuddy Operational Monitoring Method Bytecode
  • Java Agent-based Full Link Monitoring IV "JVM Memory and GC Information"
  • Java Agent-based Full Link Monitoring Five "ThreadLocal Link Tracking"
  • Java Agent-based Full Link Monitoring VI "Development and Application Level Monitoring"

Case brief
In Chapter 2, we have been able to monitor method execution time-consuming, although it can fulfill some of our basic needs, but in order to enhance code scalability, we need to use bytecode operation tool ByteBuddy to help us achieve better monitoring procedures.

Byte Buddy is a code generation and manipulation library for creating and modifying Java classes during the runtime of a Java application and without the help of a compiler. Other than the code generation utilities that ship with the Java Class Library, Byte Buddy allows the creation of arbitrary classes and is not limited to implementing interfaces for the creation of runtime proxies. Furthermore, Byte Buddy offers a convenient API for changing classes either manually, using a Java agent or during a build.

Environmental preparation
1,IntelliJ IDEA Community Edition
2. jdk1.8.0_4564 bits

Configuration information (path-related modifications for your own)
1. Configuration location: Run/Debug Configurations - > VM options
2. Configuration: - javaagent: E: itstack GIT itstack. org itstack - Demo - agent itstack - Demo - agent - 03 target itstack - Demo - agent - 03 - 1.0.0 - SNAPSHOT. jar = args

Code example

itstack-demo-agent-03
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── org.itstack.demo.agent
    │   │       ├── MethodCostTime.java
    │   │	    └── MyAgent.java
    │	└── resources
    │       └── META-INF
    │           └── MANIFEST.MF 	
    └── test
         └── java
             └── org.itstack.demo.test
                 └── ApiTest.java

pom.xml (Introduce ByteBuddy and enter it into the Agent package)

<properties>
    <!-- Build args -->
	<argline>-Xms512m -Xmx512m</argline>
	<skip_maven_deploy>false</skip_maven_deploy>
	<updateReleaseInfo>true</updateReleaseInfo>
	<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
	<maven.test.skip>true</maven.test.skip>
	<!-- custom MANIFEST.MF -->
	<maven.configuration.manifestFile>src/main/resources/META-INF/MANIFEST.MF</maven.configuration.manifestFile>
</properties>

<dependencies>
	<dependency>
		<groupId>javassist</groupId>
		<artifactId>javassist</artifactId>
		<version>3.12.1.GA</version>
		<type>jar</type>
	</dependency>
	<dependency>
		<groupId>net.bytebuddy</groupId>
		<artifactId>byte-buddy</artifactId>
		<version>1.8.20</version>
	</dependency>
	<dependency>
		<groupId>net.bytebuddy</groupId>
		<artifactId>byte-buddy-agent</artifactId>
		<version>1.8.20</version>
	</dependency>
</dependencies>

<!-- take javassist Package to Agent in -->
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-shade-plugin</artifactId>
	<executions>
		<execution>
			<phase>package</phase>
			<goals>
				<goal>shade</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<artifactSet>
			<includes>
				<include>javassist:javassist:jar:</include>
				<include>net.bytebuddy:byte-buddy:jar:</include>
                <include>net.bytebuddy:byte-buddy-agent:jar:</include>
			</includes>
		</artifactSet>
	</configuration>
</plugin>      

MethodCostTime.java

/**
 * Blog: http://itstack.org
 * Forum: http://bugstack.cn
 * Public number: bugstack wormhole stack
 * create by fuzhengwei on 2019
 */
public class MethodCostTime {

    @RuntimeType
    public static Object intercept(@Origin Method method, @SuperCall Callable<?> callable) throws Exception {
        long start = System.currentTimeMillis();
        try {
            // Execution of the original function
            return callable.call();
        } finally {
            System.out.println(method + " Method time-consuming: " + (System.currentTimeMillis() - start) + "ms");
        }
    }

}

MyAgent.java

/**
 * javaagent
 * Blog: http://itstack.org
 * Forum: http://bugstack.cn
 * Public number: bugstack wormhole stack
 * create by fuzhengwei on 2019
 */
public class MyAgent {

    //The JVM first attempts to invoke the following method on the proxy class
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("this is my agent: " + agentArgs);
        
        AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, javaModule) -> {
            return builder
                    .method(ElementMatchers.any()) // Interception of arbitrary methods
                    .intercept(MethodDelegation.to(MethodCostTime.class)); // Entrust
        };

        AgentBuilder.Listener listener = new AgentBuilder.Listener() {
            @Override
            public void onDiscovery(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {

            }

            @Override
            public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b, DynamicType dynamicType) {

            }

            @Override
            public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule javaModule, boolean b) {

            }

            @Override
            public void onError(String s, ClassLoader classLoader, JavaModule javaModule, boolean b, Throwable throwable) {

            }

            @Override
            public void onComplete(String s, ClassLoader classLoader, JavaModule javaModule, boolean b) {

            }

        };

        new AgentBuilder
                .Default()
                .type(ElementMatchers.nameStartsWith("org.itstack.demo.test")) // Specify the class to intercept
                .transform(transformer)
                .with(listener)
                .installOn(inst);
    }


    //If the proxy class does not implement the above method, the JVM will attempt to invoke the method
    public static void premain(String agentArgs) {
    }

}

MANIFEST.MF

Manifest-Version: 1.0
Premain-Class: org.itstack.demo.agent.MyAgent
Can-Redefine-Classes: true

ApiTest.java

/**
 * Blog: http://itstack.org
 * Forum: http://bugstack.cn
 * Public number: bugstack wormhole stack
 * create by fuzhengwei on 2019
 *
 * VM options: 
 * -javaagent:E:\itstack\GIT\itstack.org\itstack-demo-agent\itstack-demo-agent-03\target\itstack-demo-agent-03-1.0.0-SNAPSHOT.jar=testargs
 */
public class ApiTest {

    public static void main(String[] args) throws InterruptedException {
        ApiTest apiTest = new ApiTest();
        apiTest.echoHi();
    }

    private void echoHi() throws InterruptedException {
        System.out.println("hi agent");
        Thread.sleep((long) (Math.random() * 500));
    }

}

test result

this is my agent: testargs
hi agent
private void org.itstack.demo.test.ApiTest.echoHi() throws java.lang.InterruptedException Method time-consuming: 329ms
public static void org.itstack.demo.test.ApiTest.main(java.lang.String[]) throws java.lang.InterruptedException Method time-consuming: 329ms

Process finished with exit code 0

Focus on bugstack wormhole stack public number for source code

Topics: Java Maven jvm git