Well, the only other method I could think of would be using a custom class loader which you could register at run time. This is how frameworks like Powermock do their heavy lifting. However, this requires some setup as well, but it can be done programatically.
As long as your framework has well defined entry points and as long as all code is run from within your application, you could apply a custom class loader which could instrument all loaded classes.
However, this will not work for classes already loaded. (You could break the parent first patern, but this might raise ClassCastException
s on instances from outside your framework.)
Avoiding this would require you to override the system class loader which is equally verbose. For the sake of completeness, here is an excerpt of the javadoc of ClassLoader.getSystemClassLoader
:
If the system property "java.system.class.loader" is defined when this method is first invoked then the value of that property is taken to be the name of a class that will be returned as the system class loader. The class is loaded using the default system class loader and must define a public constructor that takes a single parameter of type ClassLoader which is used as the delegation parent. An instance is then created using this constructor with the default system class loader as the parameter. The resulting class loader is defined to be the system class loader.
In this custom class loader, you could just always return instrumented classes.
The difference between agentmain
and premain
is that the former is invoked when you attach an agent to a running JVM (via the attach API) while the latter is invoked if the agent is specified on the command line at the JVM's startup. Registering an agent at runtime might actually be a solution for you. The blog entry that I linked offers a quite good description of that.