我有一个建议,该建议在建议中称为类似的方法。我们如何确保建议仅一次和一次调用建议。现在,作为我在建议中调用的方法与所仪器的方法相同,它会递归呼叫,并在java.lang.stackoverflowerror中产生。
transform(
new AgentBuilder.Transformer.ForAdvice()
.include(JettyHandlerAdvice.class.getClassLoader())
.advice(named("addFilterWithMapping").and(ElementMatchers.takesArgument(0,named("org.eclipse.jetty.servlet.FilterHolder"))),JettyHandlerAdvice.class.getName())
)
建议
@Advice.OnMethodEnter
private static void before(@Advice.AllArguments Object[] args, @Advice.Origin("#m") String methodName, @Advice.This Object thiz) {
FilterHolder filterHolder = ((org.eclipse.jetty.servlet.ServletHandler)thiz).addFilterWithMapping(XYZFilter.class, "/*", EnumSet.of(javax.servlet.DispatcherType.REQUEST));
}
字节伙伴是一个代码生成框架,而不是面向方面的。想想将代码复制到目标位置;如果您将仪器进行了硬编码为目标方法,则您看到的堆栈溢出错误将相同。
可以通过添加标志来避免这种情况,例如,您可以在递归调用之前定义将其设置为true的ThreadLocal<Boolean>
,例如:
if (!threadLocal.get()) {
threadLocal.set(true);
try {
// your code here.
} finally {
threadLocal.set(false);
}
}
这样,您可以跟踪递归电话。但是,您确实需要某个人管理状态。一种选择是使用Instrumentation
接口将属性的持有人类的类别的属性类注入Bootstrap类加载程序。
另外,您可以检查堆栈是否有反复的调用。这不像明确的状态管理那样有效,但是从Java 9开始,您可以使用堆栈Walker API,该API便宜得多,并且可以使此通用。