I'm writing a java agent and using javassist library for modifying bytecode.
I've an agent main class (MyAgent) and a class file transformer class. MyAgent.java registers the transformer class MyClzTransformer
public class MyAgent
{
private static Instrumentation instrumentation;
public static void premain(String arg, Instrumentation inst)
{
inst.addTransformer(new MyClzTransformer());
}
}
-
public class MyClzTransformer implements ClassFileTransformer
{
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException
{
if (className.startsWith("a/b/"))
{
ClassPool clPool = ClassPool.getDefault();
System.out.println("clPool =======> " + clPool);
try
{
CtClass ctClass = clPool.get(className);
System.out.println("ct class: " + ctClass + ": methods = " + Arrays.deepToString(ctClass.getMethods()));
for(CtMethod method : ctClass.getMethods())
{
method.insertAfter("System.out.println(\" ============ added instrumented code ============ \");");
}
}
catch (NotFoundException | CannotCompileException | IOException e)
{
e.printStackTrace();
}
}
return classfileBuffer;
}
}
When I run the MyAgent jar as javaagent as following:
java -javaagent:<path to myagent.jar> a.b.MyTestProgram
I don't get any logs (sysouts) output.
Is it a classloader issue? Because, the log after clPool.get(className)
is not executing. I'm not getting any output from within try block
.
There was a basic mistake. While class name is separated by /, i.e. if (className.startsWith("a/b/"))
the same format calssName is being used to
load the class, which is not correct.
The fix is CtClass ctClass = clPool.get(className.replaceAll("/","."));