Skip to content

Instantly share code, notes, and snippets.

@tnishada
Last active November 4, 2017 12:22
Show Gist options
  • Save tnishada/c7aae1503a10596bc1f69f987a5de934 to your computer and use it in GitHub Desktop.
Save tnishada/c7aae1503a10596bc1f69f987a5de934 to your computer and use it in GitHub Desktop.
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
public class JavaAgent {
//This method is called by the jvm once the agent is attached
public static void premain(String args, Instrumentation instrumentation) {
System.out.println("Instrumentatin Agent Added ...");
instrumentation.addTransformer(new SimpleClassTransformer());
}
//This class is added to register as a transformer
private static class SimpleClassTransformer implements ClassFileTransformer {
//This method is called for every class (Except special classes) before loaded by the JVM
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
if(className.equals("Main")) { // We are only interested in the Main class
try {
// Javassist class pool
ClassPool classPool = ClassPool.getDefault();
CtClass ctMainClass = classPool.get("Main");
// get the methods of the Main class as an array
CtMethod[] methods = ctMainClass.getMethods();
for(int i = 0 ; i < methods.length; i++) {
// Iterate through the array and select the methods that we are interested
CtMethod selectedMethod = methods[i];
if(selectedMethod.getName().equals("addition")
|| selectedMethod.getName().equals("subtraction")
|| selectedMethod.getName().equals("multiplication")
|| selectedMethod.getName().equals("division")) {
//change the byte code of that method body
//add a local variable of long type
selectedMethod.addLocalVariable("nanoTime" , CtClass.longType);
//initialize the declared variable with the system time (nano seconds) at the beginning of the method
selectedMethod.insertBefore("nanoTime = System.nanoTime();");
//print the difference of the time at the end of the method
selectedMethod.insertAfter("System.out.println(\"Method execution time in Millis : \" + (1.0*System.nanoTime() - nanoTime)/1000000);");
}
}
return ctMainClass.toBytecode(); // return the instrumented class
} catch (Exception e) {
e.printStackTrace();
}
}
return new byte[0];
}
}
}
Premain-Class: JavaAgent
// new line (please remove these characters and keep the new line blank)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.alltechviewer.agent</groupId>
<artifactId>JavaAgent</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.0-GA</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
src
|------main
| '---java
| | '---JavaAgent.java
| '---resources
| '---META-INF
| '---MANIFEST.MF
pom.xml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment