3

I am trying to use ByteBuddy within a Java Agent to instrument some older libraries using OpenTracing. This is associated with the OpenTracing Contrib Java Special Agent project. I had this successfully working when using a private class member to pass the active span, but unfortunately there are instances where this is not feasible (error handling clears out the member field).

So I am trying to use ByteBuddy's ability to create local variables that can be retained from the @Advice.OnMethodEnter to the @Advice.OnMethodExit. This will allow me to create the OpenTracing Span on method enter, and finish it on method exit. I'm not sure my use case is valid, though, since I am using a transformer, which doesn't exactly match the test case for the @Advice.Local annotation.

I tried to follow the syntax used in this test case.

However, the span and scope variables are always null in the exit method. I'm a novice with ByteBuddy, so I'm sure I'm missing something basic.

public class SimpleFrameworkDispatcherAgentRule extends AgentRule {
    @Override
    public Iterable<? extends AgentBuilder> buildAgent(AgentBuilder agentBuilder) {
        return Arrays.asList(agentBuilder
                .type(named("org.simpleframework.http.core.Dispatcher"))
                .transform((builder, typeDescription, classLoader, module) -> {
                    return builder.visit(Advice.to(SimpleFrameworkDispatcherAgentRule.class)
                            .on(named("dispatch")));
                }));
    }

    @Advice.OnMethodEnter
    public static void enter(final @Advice.Origin String origin, 
            final @FieldValue(value = "request", typing = Typing.DYNAMIC) Object request, 
            final @Advice.Local("span") Object span, 
            final @Advice.Local("scope") Object scope) {
        if (isEnabled(origin)) {
            SimpleFrameworkAgentIntercept.enter(request, span, scope);
        }
    }

    @Advice.OnMethodExit
    public static void exit(final @Advice.Origin String origin, 
            final @FieldValue(value = "response", typing = Typing.DYNAMIC) Object response, 
            final @Advice.Local("span") Object span, 
            final @Advice.Local("scope") Object scope) {
        if (isEnabled(origin)) {
            SimpleFrameworkAgentIntercept.exit(response, span, scope);
        }
    }
}

I instrumented the SimpleFrameworkAgentIntercept enter and exit methods and confirmed that the variables are assigned in enter, but they are null in exit.

Randall T.
  • 187
  • 12

1 Answers1

3

You have to assign the variables, it does not help if you do this in a delegate method.

Byte Buddy uses the advice code as a template where any assignment of the local variable in a specific method is translated into an access of a local variable of the instrumented in the inlined byte code.

Java does not have pointer semantics in the sense of C or other languages. If you wanted to assign span or scope you have to do so in the annotated method itself.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192