8

私たちのアプリケーションには、いくつか(実際には多く、約30)のWebサービスがあります。各Webサービスは独自のWARファイルに常駐し、アプリケーションの起動時に初期化される独自のSpringコンテキストを持っています。

また、Webサービスクラスに適用するアノテーション駆動型のアスペクトクラスもいくつかあります。最初のpoincut式は次のようになりました。

@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..))")
  public void methodsToBeLogged() {
  }

また、AOPは、構成への入力を通じてサービスで有効になりました。

しかし、Webサービスの数が増えるとOutOfMemoryException、サーバーでsを経験し始めました。いくつかのプロファイリングと分析を行った後、AspectJExpressionPointcutクラスのインスタンスによって保持されているキャッシュによってメモリが使用されているように見えました。

各インスタンスのキャッシュは約5MBでした。また、3つの側面と30のサービスがあるため、合計で450MBのデータを保持する90のインスタンスが生成されました。

キャッシュの内容を調べたところ、my.package.service.businessパッケージの一部ではないクラスも含め、WARに存在するすべてのクラスのJavaリフレクションメソッドインスタンスが含まれていることがわかりました。ポイントカット式を変更して、追加のwithin句を追加した後:

@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..)) && 
within(my.package.service.business..*)")
  public void methodsToBeLogged() {
  }

メモリ使用量は再び通常に低下しました。そして、すべてのAspectJExpressionPointcutインスタンスは、全体で1MB未満しかかかりませんでした。

誰かがそれがなぜであるか説明できますか?そして、なぜ最初のポイントカット式では不十分なのですか?のキャッシュがAspectJExpressionPointcut共有されないのはなぜですか?

4

1 に答える 1

12

AspectJExpressionPointcutは、ポイントカット式に基づいて、AOPを特定のメソッド呼び出しに適用するかどうかの決定を高速化するキャッシュ(shadowMatchCache)を使用します。このキャッシュは、多くのメモリを消費する可能性があります。

さらに、特定のBeanのすべてのメソッドを提供して、ポイントカット式が一致するかどうかを確認する前に、Springはまず、AspectJExpressionPointcut.matches(Class targetClass)を呼び出して、Beanクラスが一致する可能性があるかどうかを確認します。このメソッドは、AspectJのPointcutExpressionImpl.couldPossiblyMatch()メソッドに委任します。これにより、クラスが「おそらく」ポイントカット式に一致するか、「完全に」一致しないかどうかをすばやくチェックします。インサイドポイントカットを使用しているAspectJ開発者によると、結果はより明確なノーになります。また、スタンドアロンの種類のポイントカット(実行、呼び出し、取得、設定)を使用しないことをお勧めしますが、これらを内で組み合わせます

ただし、shadowMatchCacheは、ポイントカット式ごとに一致した結果または一致しなかった結果が含まれているため、共有できません。

ただし、少なくとも、キャッシュされるものを制限することができます。また、applicationContextが開始されると、Springはこのキャッシュ全体を保持しないことで、これを改善できる可能性があると思います。新しいBeanがすでに開始された後にapplicationContextに動的に追加された場合、一致の一部をやり直すことを犠牲にして、一致しないものをすべて破棄する可能性があります。

AspectJExpressionPointcutクラス内で発生する可能性のあるもう1つのメモリは、pointCutParserです。このパーサーは、applicationContext内のすべてのAspectJExpressionPointcuts間で共有される可能性があります。JIRAチケットSPR-7678で戦利品を取ります。

于 2010-11-10T12:31:32.527 に答える