如何正确有效地使用ByteBuddy的指南

问题描述 投票:0回答:1

我看了ByteBuddy的文档,也看了一些使用ByteBuddy的Java代理实现。但我仍然不清楚什么是使用ByteBuddy代理的正确方法。

这是我用来引导代理的代码。

public class ByteBuddyAgent {

    public static void premain(String arguments, Instrumentation instrumentation) {

        System.out.println("Bootstrapping ByteBuddy Agent");


        new AgentBuilder.Default()
                .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
                .type(ElementMatchers.hasSuperClass(ElementMatchers.nameContains("Level1")))
                .transform(new ByteBuddyTransformer()
                .installOn(instrumentation);

    }

    private static class ByteBuddyTransformer implements AgentBuilder.Transformer{

        @Override
        public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription,
                                                ClassLoader classLoader, JavaModule module) {

            return builder.method(ElementMatchers.named("printLevel"))
                    .intercept(Advice.to(MethodTracker.class));
        }
    }
}

这是我的Advice类,我尝试了Advice支持的不同注解,效果很好。

public class MethodTracker {

    @Advice.OnMethodEnter
    public static Object onMethodBegin(@Advice.This Object invokedObject, @Advice.AllArguments Object[] arguments,
                                       @Advice.FieldValue("name") Object fieldValue, @Advice.Origin Object origin,
                                       @Advice.Local("localVariable") Object localVariable) {
        System.out.println("=======on Method Begin Running with ByteBuddy=======, " + invokedObject);
        System.out.println("======Printing arguments=======");
        for(Object obj: arguments){
            System.out.println("Argument:: " + obj);
        }
        localVariable = "Gunika";

        System.out.println("FieldValue:: " + fieldValue);
        System.out.println("Origin:: " + origin);
        return "ReturningStateFromOnMethodBegin";
    }

    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
    public static void onMethodEnd(@Advice.This Object invokedObject, @Advice.Return Object returnValue,
                                   @Advice.FieldValue("name") Object fieldValue, @Advice.Enter Object state,
                                   @Advice.Local("localVariable") Object localVariable){
        System.out.println("=======on Method End Running with ByteBuddy======= " + invokedObject);

        System.out.println("Return value is " + returnValue);
        System.out.println("FieldValue:: " + fieldValue);
        System.out.println("FieldValue:: " + fieldValue);
        System.out.println("State:: " + state);
        System.out.println("LocalVariable:: " + localVariable);
    }
}

我的问题如下。

  • 现在在我的示例应用中,我只尝试了1条规则的匹配,但如果有 "n "条规则,我想应用什么来实现呢?

  • 有初始的规则集,是应用provided到代理。现在让我们说,在某个时间点,我想添加另一个规则。正确的实现方式是什么?

  • 我们创建的AgentBuilder实例是否应该在Java Agent中只创建一次?

  • 任何其他在使用ByteBuddy代理时应该注意的信息都会有所帮助。

bytecode instrumentation byte-buddy
1个回答
0
投票

Advice.to(MethodTracker.class) 是相当昂贵的。如果你仪表很多类,又想花费内存,我建议你重用实例,它是不可变的。

别的不说了。@Advice.AllArguments 比使用读取特定参数的专门建议类更昂贵,如果你能负担得起的话。然而,这是一个JVM的问题,而不是Byte Buddy特有的问题。您可以使用 -Dnet.bytebuddy.dump=/some/folder 来查看生成了哪些字节码。昂贵的地方往往在于埋没了你去做什么构造。

© www.soinside.com 2019 - 2024. All rights reserved.