[Seasar-user:20297] [S2Container]マルチスレッド処理時にCyclicReferenceRuntimeException
[E-MAIL ADDRESS DELETED]
[E-MAIL ADDRESS DELETED]
2010年 11月 1日 (月) 18:00:34 JST
お世話になります、齊藤と申します。
現在、S2Containerを使った、
マルチスレッドによるバッチ処理の検証を行っております。
その検証の中で、稀にですが、
CyclicReferenceRuntimeExceptionが発生することがあります。
この例外が発生する原因、および解決策をご教授願いたく。
以下、検証時の大まかな構成と、
現時点で分かっている情報になります。
●検証で利用したS2のバージョン
・S2Framework 2.4.39
・S2Extension 2.4.39
・S2Tiger 2.4.39
●検証用アプリの構造(diconファイルに登録した主要コンポーネントのみ抜粋)
Aクラス(instance="ptototype") -------> Bクラス(instance="prototype"
)
↑
Bクラス用InterceptorAdapter(
以下のInterceptorを保持、Bクラスにaspect)
- CInterceptor(
instance="prototype")
- DInterceptor(
instance="prototype")
- Eクラス(
instance="singleton"、Stringフィールドを複数保持するBeanクラス、
DInterceptorにDI)
※上記AクラスからBクラスの呼び出しを、複数スレッドで同時に実行
今回の検証では、1回の処理で同時に10スレッド実行
●発生する例外の詳細(一部加工しています)
org.seasar.framework.beans.IllegalPropertyRuntimeException: [ESSR0059]クラ
ス(DInterceptor)のプロパティ(Eクラス)の設定に失敗しました。理由は
org.seasar.framework.container.CyclicReferenceRuntimeException:
[ESSR0047]Eクラスで循環参照が発生しました
at
org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:297)
at
org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindAuto(AbstractBindingTypeDef.java:149)
at
org.seasar.framework.container.assembler.BindingTypeMustDef.doBind(BindingTypeMustDef.java:45)
at
org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:91)
at
org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:50)
at
org.seasar.framework.container.assembler.AccessTypeFieldDef.bind(AccessTypeFieldDef.java:42)
at
org.seasar.framework.container.assembler.AutoPropertyAssembler.assemble(AutoPropertyAssembler.java:56)
at
org.seasar.framework.container.deployer.PrototypeComponentDeployer.deploy(PrototypeComponentDeployer.java:43)
at
org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:111)
at
org.seasar.framework.aop.interceptors.InterceptorAdapter.invoke(InterceptorAdapter.java:67)
at Bクラス
$$EnhancedByS2AOP$$19a37a$$MethodInvocation$$execute2.proceed(MethodInvocationClassGenerator.java)
at Bクラス$$EnhancedByS2AOP$$19a37a.execute(Bクラス
$$EnhancedByS2AOP$$19a37a.java)
at Aクラス.execute(Bクラス.java:999)
(中略)
Caused by: org.seasar.framework.container.CyclicReferenceRuntimeException:
[ESSR0047]Eクラスで循環参照が発生しました
at
org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:59)
at
org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:48)
at
org.seasar.framework.container.impl.ComponentDefImpl.getComponent(ComponentDefImpl.java:111)
at
org.seasar.framework.container.impl.S2ContainerImpl.getComponent(S2ContainerImpl.java:129)
at
org.seasar.framework.container.assembler.AbstractBindingTypeDef.getValue(AbstractBindingTypeDef.java:295)
(以下略)
●発生する例外の補足
・上記例外は、20回に1回出るか出ないかくらいの頻度で発生
・最新のS2のバージョンでも、同様の例外が発生するのを確認
・「循環参照が発生」と出るが、上記EクラスはStringのみ保持、かつDIしてい
るフィールドはない
・Eクラスから別のクラス(instanceはsingleton)に差し替えても、同様の例外
が発生することがある
・prototypeのコンポーネントにsingletonのコンポーネントをDIするときに
発生する模様
・Bクラス用InterceptorAdapterをInterceptorChainに変更すると、上記例外が
発生しない
・試行回数が少ないだけ?
・Interceptorのinstanceはprototypeにしたいため、できれば
InterceptorAdapterを使いたい
・シングルスレッド時には、上記例外は発生しない
●原因に関する個人的見解
・org.seasar.framework.container.deployer.SingletonComponentDeployerにて
、
以下の順序で処理が走ったのではないか、と予想
1. スレッド1・スレッド2がほぼ同時に
SingletonComponentDeployer#deploy()メソッドを呼び出す
2. 1.の時点でcomponentフィールドはnullのため、
スレッド1・スレッド2共に47行目のif文がtrueとなり、assemble()メソ
ッドを呼び出す(48行目)
3. スレッド1が62行目を先に呼び出して、instantiatingフィールドにtrue
をセットする
4. スレッド2が58行目に到達、3によりinstantiatingフィールドがtrueにさ
れたため59行目に到達
→ 上記例外発生
長くなりましたが、
上記問題への対応策等をご教授頂けますでしょうか?
以上、よろしくお願い致します。
==========
齊藤 雅志
-------------- next part --------------
HTMLの添付ファイルを保管しました...
URL: <http://ml.seasar.org/archives/seasar-user/attachments/20101101/027629a6/attachment.html>
Seasar-user メーリングリストの案内