Search code examples
javainstrumentationjavassistjavaagents

javaagent (written using Javassist) not working properly


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.


Solution

  • 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("/","."));