如何避免与字节伙伴的递归调用 - java.lang.StackOverflowError [英] how to avoid recursive calls with byte buddy - java.lang.StackOverflowError

查看:73
本文介绍了如何避免与字节伙伴的递归调用 - java.lang.StackOverflowError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个建议,它在建议中调用了类似的方法.我们如何确保该建议被调用一次且仅一次.现在,由于我在通知中调用的方法与被检测的方法相同,它进入递归调用并导致 java.lang.StackOverflowError.

I have an advice which calls a similar method in the advice. How do we make sure the advice gets called once and only once. Right now as the method I am calling within advice is the same as the one being instrumented, it goes into recursive calling and results in 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));
    }

推荐答案

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

Byte Buddy is a code generation framework and is not aspect-oriented. Think of the code being copy-pasted to the target location; the stack overflow error you are seing would be the same if you hardcoded the instrumentation into your target method.

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

This can be avoided by adding a flag, for example, you could define a ThreadLocal<Boolean> that you set to true before making a recursive call, for example:

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

通过这种方式,您可以跟踪递归调用.但是,您确实需要在某个家中管理您的州.一种选择是使用 Instrumentation 接口将您的财产的持有者类注入引导类加载器.

This way, you can keep track of a recursive call. You do however need to manage your state somehome. One option would be to inject a holder class for your property into the bootstrap class loader using the Instrumentation interface.

或者,您可以检查堆栈中的递归调用.这不如显式状态管理那么有效,但从 Java 9 开始,您可以使用 Stack walker API,它更便宜且易于使用.

Alternatively, you can check the stack for a recurive call. This is not as efficient as the explicit state management but starting with Java 9, you can use the stack walker API which is much cheaper and makes this approachable.

这篇关于如何避免与字节伙伴的递归调用 - java.lang.StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆