ByteBuddy:如何在转换方法时跨 enter/exit 添加局部变量

ByteBuddy: how to add local variable across enter/exit when transforming a method

我正在尝试在 Java 代理中使用 ByteBuddy,以使用 OpenTracing 检测一些较旧的库。这与OpenTracing Contrib Java Special Agent project有关。当使用私有 class 成员传递活动跨度时,我成功地完成了这项工作,但不幸的是,在某些情况下这是不可行的(错误处理清除了成员字段)。

所以我正在尝试使用 ByteBuddy 的能力来创建可以从 @Advice.OnMethodEnter@[=35 保留的局部变量=]。这将允许我在方法进入时创建 OpenTracing Span,并在方法退出时完成它。不过,我不确定我的用例是否有效,因为我使用的是转换器,它与 @Advice.Local 注释的测试用例不完全匹配。

我尝试遵循 this test case 中使用的语法。

但是,span 和 scope 变量在退出方法中始终为 null。我是 ByteBuddy 的新手,所以我确定我缺少一些基本的东西。

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);
        }
    }
}

我检测了 SimpleFrameworkAgentIntercept 的进入和退出方法,并确认变量在进入时已分配,但在退出时为空。

你必须分配变量,如果你在委托方法中这样做没有帮助。

Byte Buddy 使用建议代码作为模板,其中特定方法中对局部变量的任何赋值都被转换为对内联字节代码中检测的局部变量的访问。

Java 没有 C 或其他语言意义上的指针语义。如果你想分配 spanscope 你必须在注释方法本身中这样做。