A Java Agent, once registered with the class loader, has a single method:
A Java Agent is given the option of modifying the array of bytes representing the class before the class loader finishes the class loading process. Here is a specification of class loading. In a nutshell, the bytes are given to the Java Agent after the class loader has retrieved them but before Linking. Your Java Agent can create a new byte array in a valid class file format and return it or, if it is not performing a transformation, return null.
Here is an example that simply prints a message like the following:
How do you get all of this to work? Here’s what you’ll need to do:
- Create an Implementation of ClassFileTransformer
- Create a class with a premain method (could be in the first class, but but that would violate The Single Responsibility Principle.
- Create jar file
- Star the VM with a command line parameter.
And, of course, are the details for each of those steps.
Create an Implementation of ClassFileTransformer
The Java Agent class above is a complete example of a class that can “transform” a just-loaded class. By itself, it really does not do much. However, if you’d like to perform some custom transformation, you could create a new byte array, add in some Java Bytecodes and then return that class instead.
Why would you do this? Here are a few examples:
- You’re adding logging code to a class
- Custom implementation of AOP
- Instrument a class to better thread-based testing (my reason for looking into this in the first place)
- Etc.
Create a class with a premain method
The class file transformer is not directly added to the class loader. Instead, you create another class with a method called premain that instantiates the class and registers it. Here is a complete example:
Why this indirection? I’m not exactly sure. However, I use it to write the registrar once and reuse it across projects. The act of registration is the same, what I want to register varies by project. The Registrar.jar file you’ll download is essentially a simple “component” that allows for registration of a ClassFileTransformer you create in your project by specifying a system property.
Create Jar File
When you add a class file transformer to the class loader, you must specify the name of a jar file. You cannot simply name a class in the classpath. So if the ClassAndPackageNamePrintingClassFileTransformer is in the class path, then you need to add the class RegisterMyClassFileTransformer to a jar file and add a manifest file to specify it.
The jar file needs to have the following structure:
The contents of the MANIFEST.MF file, at a minimum, would be:
NOTE: If you happen to download the Eclipse project mentioned here, you can simply find the RecreateJar.jardesc file in the Eclipse project, right-click and select Create JAR.
Start the VM
Finally, we need to star the VM:
Comments