【问题标题】:how to avoid recursive calls with byte buddy - java.lang.StackOverflowError如何避免使用字节伙伴进行递归调用 - java.lang.StackOverflowError
【发布时间】:2017-04-21 10:56:50
【问题描述】:

我有一个建议,它在建议中调用了类似的方法。我们如何确保只调用一次建议。现在,由于我在通知中调用的方法与被检测的方法相同,因此它进入递归调用并导致 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));
    }

【问题讨论】:

    标签: servlet-filters byte-buddy


    【解决方案1】:

    Byte Buddy 是一个代码生成框架,不是面向方面的。考虑将代码复制粘贴到目标位置;如果您将检测硬编码到目标方法中,您看到的堆栈溢出错误将是相同的。

    这可以通过添加一个标志来避免,例如,您可以在进行递归调用之前定义一个 ThreadLocal<Boolean> 并将其设置为 true,例如:

    if (!threadLocal.get()) {
      threadLocal.set(true);
      try {
        // your code here.
      } finally {
        threadLocal.set(false);
      }
    }
    

    这样,您可以跟踪递归调用。但是,您确实需要在某个地方管理您的状态。一种选择是使用Instrumentation 接口将您的属性的持有者类注入到引导类加载器中。

    或者,您可以检查堆栈是否有递归调用。这不如显式状态管理高效,但从 Java 9 开始,您可以使用更便宜且易于使用的 stack walker API。

    【讨论】:

      猜你喜欢
      • 2021-09-20
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多