2017-04-21 2 views
1

J'ai un conseil qui appelle une méthode similaire dans le conseil. Comment pouvons-nous nous assurer que le conseil est appelé une fois et qu'une seule fois. À l'heure actuelle, comme la méthode que j'appelle dans le conseil est la même que celle qui est instrumentée, elle va dans l'appel récursif et aboutit à java.lang.StackOverflowError.comment éviter les appels récursifs avec byte buddy - 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()) 
         ) 

conseils

@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)); 
    } 

Répondre

0

Byte Buddy est un cadre de génération de code et n'est pas orienté aspect. Pensez au code copié-collé à l'emplacement cible; l'erreur de débordement de pile que vous regardez serait la même si vous avez codé en dur l'instrumentation dans votre méthode cible.

Cela peut être évité en ajoutant un drapeau, par exemple, vous pouvez définir un ThreadLocal<Boolean> que vous définissez à true avant de faire un appel récursif, par exemple:

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

De cette façon, vous pouvez garder une trace de un appel récursif. Vous avez cependant besoin de gérer votre état somehome. Une option serait d'injecter une classe de support pour votre propriété dans le chargeur de classe bootstrap en utilisant l'interface Instrumentation.

Vous pouvez également vérifier la pile pour un appel récurrent. Ce n'est pas aussi efficace que la gestion d'état explicite mais en commençant par Java 9, vous pouvez utiliser l'API stack walker qui est beaucoup moins chère et qui rend cette approche accessible.