Sunday, November 5, 2017

Java Instrumentation Agent


A Java-agent is a special program which can be used to inspect or modify another Java program at run time. Java agents were introduced with the Java Instrumentation package in JDK 1.5.

Java agents are mostly used for Debugging, Profiling and Logging a program.

Let's see how Java-agents works by using a simple example
 
In this example we are creating a Java-gent which calculate the execution time of a method and print the time on terminal.

In order to understand this code, you should be familiar with following technologies

  • Java programming 
  • Maven build tool
  • How to create a jar file (Agent is built as a jar file)

In this example we are creating a calculator program. This calculator program is the class to be instrumented by the Java-agent class.


You can save this code in a file named Main.java and run this class from terminal by using following commands.
 javac Main.java                                                        
 java Main                                                           
It will show an output similar to this
Addition : 36
Subtraction : 24
Multiplication : 180
Division : 5.0
Let's create the Java-agent

You need to create 3 files for the Java-agent program.
1. JavaAgent.java
2. pom.xml (Maven)
3. MANIFEST.MF (jar manifest file)

JavaAgent.java
premain method act as the main method of the java agent. This method is executed by the JVM once the agent is attached. Here we are creating a class named SimpleClassTransformer which implements the ClassFileTransformer interface and it has a method named transform. Once the agent attached every class (Except some bootstrap time classes and some classes upon which JavaAgent depends) is passed through this method before the specific class is loaded by the Java class loader.
Read the comments added in the JavaAgent.java file for more information.

MANIFEST.MF 
This file contain the Pre-main class name. JVM find the class name to execute from this file. (There should be a new line at the end of each line of a mainfest file to work properly)

pom.xml
This file contains the dependencies required for the agent program. Here we are using Javassist which is a great library for instrumenting java classes. You can get more information on it through this link. (Javassist)

Instructions to run the program
  • Go to the folder containing src folder and the pom.xml file and build the project using mvn package command.
  • If the build is successful there will be a new jar file named JavaAgent-1.0-SNAPSHOT.jar in the target folder.
  • Now you need to add this jar file as the java-agent  of the first program(calculator) and execute it again.
  • Go to the folder containing calculator program which we have developed earlier. There should be two files(Main.java, Main.class)  in that folder since we have compiled it earlier. 
  • Now execute the following command.
java -cp "/absolute/path/to/javassist-3.18.0-GA.jar:./" -javaagent:"/path/to/JavaAgent-1.0-SNAPSHOT.jar" Main
  • Then you will see an output similar to this
Instrumentatin Agent Added ...
Method execution time in Millis : 0.013584
Addition : 36
Method execution time in Millis : 0.001592
Subtraction : 24
Method execution time in Millis : 0.001158
Multiplication : 180
Method execution time in Millis : 0.001265
Division : 5.0 
This example is shown using a Linux environment if you are on a different operating system then you need to change the terminal commands specific to the relevant operating system. Please share your questions, ideas, & suggestions by commenting below.