lundi 7 janvier 2019

Efficiently get caller in byte buddy's MethodDelegation

I am trying to build a call tree in my java agent with byte buddy library. To add elements to the tree I want to use method delegation. However, to make sure who is the parent of any leaf, I need to know who called the method.

I don't want to use:

sun.reflect.Reflection#getCallerClass(int)

Because it's deprecated and unavailable in Java 8+. Also, I tried:

public class ThreadUtil {

public static StackTraceElement getCaller() {
    Instant now = Instant.now();
    StackTraceElement ste = Thread.currentThread().getStackTrace()[3];
    String callerClass = ste.getClassName();
    String callerMethod = ste.getMethodName();
    Instant now2= Instant.now();
    System.out.println(Duration.between(now, now2));
    return ste;
}

}

But, it's extremely slow(~1 ms - too much if I have thousands of calls).

Is there a way to get caller efficiently at this point (maybe some byte buddy's tricks)?

P.S. My agent:

private static void instrument(String agentOps, Instrumentation inst) {
    System.out.println("Agent");
    new AgentBuilder.Default().with(new Eager())
            .ignore(ElementMatchers.nameContains("com.dvelopp.agenttest"))
            .type((ElementMatchers.any()))
            .transform((builder, typeDescription, classLoader, module) -> builder.method(ElementMatchers.any())
                    .intercept(MethodDelegation.to(Interceptor.class))).installOn(inst);
}

public static class Interceptor {

    @RuntimeType
    public static Object intercept(@SuperCall Callable<?> zuper, @Origin Method method,
                                   @AllArguments Object[] args, @This(optional = true) Object me) throws Exception {
        System.out.println("CURRENT: " + method.getDeclaringClass().getName());
        System.out.println("CALLER: " + ThreadUtil.getCaller().getClassName());
        return zuper.call();
    }

}





Aucun commentaire:

Enregistrer un commentaire