package de.codecentric.performance.agent.allocation; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.security.ProtectionDomain; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * ClassFileTransformer implementation which will use ASM to visit the bytecode of constructors of classes matching the * given prefix. The actual modification of the constructor bytecode is performed by ConstructorVisitor. */ public class AllocationTrackerClassFileTransformer implements ClassFileTransformer { private String prefix; public AllocationTrackerClassFileTransformer(String prefix) { this.prefix = prefix; if (prefix.startsWith("java")) { AgentLogger.log("You are trying to instrument JVM core classes - this might crash the JVM"); } } @Override public byte[] transform(ClassLoader loader, final String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (className.startsWith(TrackerConfig.AGENT_PACKAGE_PREFIX)) { // Safeguard: do not instrument our own classes return classfileBuffer; } if (!className.startsWith(prefix)) { return classfileBuffer; } ClassReader classReader = new ClassReader(classfileBuffer); ClassWriter classWriter = new ClassWriter(classReader, 0); ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM5, classWriter) { @Override public MethodVisitor visitMethod(int access, String methodName, String desc, String signature, String[] exceptions) { MethodVisitor methodVisitor = super.visitMethod(access, methodName, desc, signature, exceptions); if (methodName.equals("<init>")) { return new ConstructorVisitor(className, methodVisitor); } return methodVisitor; } }; classReader.accept(classVisitor, 0); return classWriter.toByteArray(); } }