使用bytebuddy从拦截方法调用lambda会引发java.lang.NoClassDefFoundError:
我正在尝试使用ByteBuddy和java代理进行一些插装。在其中一个步骤中,我想捕获stacktrace并用我关心的调用对其进行过滤。让我们想象一个premain函数如下所示:使用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()
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()的事情。这是你的建议吗?是的,但是你需要从变压器内部进行操作。