使用bytebuddy从拦截方法调用lambda会引发java.lang.NoClassDefFoundError:

使用bytebuddy从拦截方法调用lambda会引发java.lang.NoClassDefFoundError:,java,noclassdeffounderror,byte-buddy,javaagents,Java,Noclassdeffounderror,Byte Buddy,Javaagents,我正在尝试使用ByteBuddy和java代理进行一些插装。在其中一个步骤中,我想捕获stacktrace并用我关心的调用对其进行过滤。让我们想象一个premain函数如下所示: public class SeleniumReporter { public static void premain(final String agentArgs, final Instrumentation inst) { new AgentBuilder.Default()

我正在尝试使用ByteBuddy和java代理进行一些插装。在其中一个步骤中,我想捕获stacktrace并用我关心的调用对其进行过滤。让我们想象一个premain函数如下所示:

public class SeleniumReporter {
    public static void premain(final String agentArgs, final Instrumentation inst) {

        new AgentBuilder.Default()
                .with(new AgentBuilder.InitializationStrategy.SelfInjection.Eager())
                .type(named("org.openqa.selenium.remote.RemoteWebDriver"))
                .transform((builder, type, classLoader, module) -> builder
                        .method(nameStartsWith("findElement")
                                .and(takesArguments(By.class).or(takesArguments(String.class, String.class)))
                                .and(isPublic())
                        )
                        .intercept(Advice.to(FindElementInterceptor.class))
                )
                .installOn(inst);
    }
}
拦截器的形式如下:

public class FindElementInterceptor {
    @Advice.OnMethodExit
    public static void log(@Advice.This RemoteWebDriver driver, @Advice.Origin String method, @Advice.AllArguments Object[] args) {
        /*
        ... Some extra code
        */
        
        final String stackTrace = Arrays.stream(Thread.currentThread().getStackTrace())
                .map(t -> String.format("%s:%s", t.getClassName(), t.getMethodName()))
                .filter(s -> !s.startsWith("org.codehaus.plexus."))
                .filter(s -> !s.startsWith("org.apache.maven."))
                .collect(Collectors.joining(";"));

        System.out.println(stackTrace);
    }
}

运行该代码将抛出java.lang.NoClassDefFoundError,因为未加载lambda表达式。因此,我的问题是:我能做些什么来确保有负载?我正在考虑创建一个类,并通过ByteBuddy加载所有UTIL。还有更优雅的方法吗?

Byte Buddy无法将lambda表达式从advice方法复制到目标方法。从技术上讲,lambda是定义它的类中唯一的私有方法,目标类将不可用


使用常规迭代来避免这个问题。或者,您需要在单个类中实现表达式,并使用
ClassInjector

将这些类注入目标类加载器,非常感谢您的回答。我是在看这一类的东西。但是我不明白如何在AgentBuilder中使用ClassInjector。我想做一些类似agentbuilder.type().transform().transform().installOn()的事情。这是你的建议吗?是的,但是你需要从变压器内部进行操作。