2017-04-21 21 views
1

私はアドバイスで同様のメソッドを呼び出すアドバイスを持っています。アドバイスが一度だけ呼び出されるようにするにはどうすればよいでしょうか。私がアドバイスの中で呼び出すメソッドはインストゥルメントされているメソッドと同じですが、これは再帰呼び出しとjava.lang.StackOverflowErrorの結果になります。バイトバディで再帰呼び出しを避ける方法 - 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)); 
    } 

答えて

0

バイトバディは、コード生成フレームワークであり、アスペクト指向ではありません。コピー先の場所にコードがコピーされていると考えてください。インストルメンテーションをターゲットメソッドにハードコーディングしている場合は、スタックオーバーフローエラーが発生します。

これはフラグを追加することによって回避することができ、例えば、あなたがたとえば、あなたが再帰呼び出しを行う前にtrueに設定ThreadLocal<Boolean>定義することができます。

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

この方法では、あなたがを追跡することができます再帰呼び出し。しかしあなたはあなたの州を管理する必要があります。 1つのオプションは、Instrumentationインターフェイスを使用して、ブートストラップクラスローダーにプロパティのホルダークラスを注入することです。

また、再帰呼び出しのスタックをチェックすることもできます。これは、明示的な状態管理と同じくらい効率的ではありませんが、Java 9からは、はるかに安価なスタックウォーカーAPIを使用できます。

関連する問題