A Java Agent Example (-javaagent)

Since Java 5 developers have the possibility to define so called pre-main hooks to manipulate the execution of a Java program at runtime with Java agents. An agent as part of the classpath is triggered before execution of the main method and therefor can be used to either filter calls to or even manipulate the underlying Java code. A tool for code manipulation is javassists. Apache Ranger for example is using both java agents and javassits to override the authorization mechanism of components of the Hadoop stack. This together with Ranger Stacks could also be used to secure existing code unchanged during runtime.

In this post we are going to look a very basic example of using Java agents to manipulate existing code.

The Name Checker

For this example a simple name checker is manipulated to throw an exception when “Dr.No” is entered. The name checker itself does not distinguish between any names. Just the injection of NameCheckerAgent changes the behavior of an existing jar as demonstrated here:

The CheckName application has two basic classes responsible for taking the name as an argument. The pseudo NameChecker simply returns true. Only the NameCheckerAgent is responsible for throwing an exception when the given argument is “Dr.No”.

NameCheckerAgent

The NameCheckerAgent.class is the point of entry for the the pre-main hook which is executed before the main method. In the MANIFEST.MF the class with the pre-main method is set by applying the Premain-Class parameter.

The pre-main method checks for given arguments being equal to the defined initialization parameter. If both are equal the Instrumentation API is being used to manipulate the existing code base. A so called Transformer, in this case the CheckNameTransformer is being injected. An agent provides an implementation of this interface in order to transform class files. The transformation occurs before the class is defined by the JVM.

When there are multiple transformers, transformations are composed by chaining the transform calls. That is, the byte array returned by one call to transform becomes the input (via the classfileBuffer parameter) to the next call.

The CheckNameTransformer is an implementation of the ClassFileTransformer interface, where class file is being used as defined in the Java Virtual Machine Specification to mean a sequence of bytes in class file format, whether or not they reside in a file. The transform method is called during processing, before the class file bytes have been verified or applied.

With the help of javassits the check method of NameChecker is altered in that way, that the call of the check method of the NameCheckerAgent is executed before it. Besides the insertBefore there is insertAt to change the code at a specific line of the method or insertAfter to define a function being executed after the check method.

In the NameCheckerAgent we check for Dr.No and throw an exception when the argument given matches.

Further Readings

One thought on “A Java Agent Example (-javaagent)”

Leave a Reply

Your email address will not be published. Required fields are marked *