How to instrument java methods and register callbacks implemented in java agent

165 Views Asked by At

I am writing a java agent to instrument user annotated methods. Currently, with javassist, I can identify the annotated methods and insert logging information. However, I am wondering how I can instrument the methods to call java agent callbacks. Following is the transform method. I want to call a custom agent method by insertBefore and insertAfter.

   @Override
   public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                            ProtectionDomain protectionDomain, byte[] classfileBuffer)
            throws IllegalClassFormatException {

        byte[] byteCode = classfileBuffer;
        
        try {
            ClassPool classPool = scopedClassPoolFactory.create(loader, rootPool,
                        ScopedClassPoolRepositoryImpl.getInstance());
            CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer));
        
                          
            CtMethod[] methods = ctClass.getDeclaredMethods();

            for (CtMethod method : methods) {
                Annotation annotation = getAnnotation(method);
                if (annotation != null) {
                    log.info("Going to Transform the class " + className);
                    method.insertAfter("System.out.println(\"Logging using Agent\");");
                }
            }
            byteCode = ctClass.toBytecode();
            ctClass.detach();
        } catch (Throwable ex) {
            log.log(Level.SEVERE, "Error in transforming the class: " + className, ex);
        }
        return byteCode;
   }


1

There are 1 best solutions below

0
Proy On

I wanted to post the answer to my question in case it helps others. I created a singleton TraceTool class with TraceStart and TraceEnd methods.

package com.example.monitoring;


public class TraceTool {
    private static TraceTool ins = new TraceTool();

    public static TraceTool getInstance() {
        return ins;
    }

    public void traceStart(){
        System.out.println("Hello!!!! This is Trace Tool: We intercepted function start!!!!!!");
    }
    public void traceEnd(){
        System.out.println("This is Trace Tool: We intercepted function End! Bye!!!!!");
    }
}

Then I inject these methods using javassist.

method.insertAfter("com.example.monitoring.TraceTool.getInstance().traceStart();");
method.insertAfter("com.example.monitoring.TraceTool.getInstance().traceEnd();");