The java.lang.instrument package allows a programmer to modify classfiles
as they are loaded. No API for doing the modifications is supplied, but you
can use ASM or BCEL etc to do that. This example prints out class names as
they are loaded.
package inst; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; public class Instrument { public static void premain(String options, Instrumentation ins) { ins.addTransformer(new Logger() ); } public static void main(String args[] ) { System.out.println("Hello World" ); } public static class Logger implements ClassFileTransformer { public byte[] transform(java.lang.ClassLoader loader, java.lang.String className, java.lang.Class classBeingRedefined, java.security.ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { System.err.println(className ); return null; } } }
It is run using the new javaagent parameter:
java -javaagent:inst.Instrument inst.Instrument
Output:
java/lang/StringCoding java/lang/ThreadLocal$ThreadLocalMap java/lang/ThreadLocal$ThreadLocalMap$Entry java/lang/StringCoding$CharsetSD java/lang/StringCoding$StringDecoder Hello World
I presume that classes like java.lang.String are loaded prior to the agent
class being hooked up. Also, beware that
it is possible to deadlock the classloading mechanism if you aren't careful
– only modifying classes that don't match a regexp like
“java.*|sun.*|javax.*” is a good idea!