[Seasar-user:15750] s2-extension:HashMap の無限回廊

Shinichi_TAKEUCHI [E-MAIL ADDRESS DELETED]
2008年 9月 12日 (金) 21:02:36 JST


お世話になります、工楽房の竹内と申します。

以下のような状況で、無限ループになる場合があります。
場所は、次のメソッドです。
org.seasar.extension.dxo.converter.impl.ConverterFactoryImpl.getConverter(ConverterFactoryImpl.java:106)

■状況
1)マルチコアマシン、マルチスレッドOS(JVM)
   Solaris10-Sparc:32Core-CPUs / 64bitJVM
2)高負荷での多重処理
   MultiThread で 300TPS 程度

■現象
1)突然CPUが100%近くになる
2)ThreadDumpするとBlockされているものがない
  9つのThreadが java.util.HashMap.get にて実行中(RUNNABLE)

■考察
  調査してみると、[参考1]のような@ITの記事がみつかりました。
  概要としては、NormalなHashMapはMultiThread環境において、内部のLinkedList状のデータがLoopしてしまい、get()などが無限ループになることがあるようです。
 [参考1]:http://www.atmarkit.co.jp/fjava/rensai4/troublehacks10/troublehacks10_1.html

■考えられる対策
 DXOは、そもそもAutoDeployなどではSingleton指定であり、MultiThreadで使用されることが前提であることから以下のような対策が考えられます。
 いかがでしょうか?
1)ConcurrentMap を使用する
   Java1.5以上に限定されます
2)問題となるメソッドまたはその一部をSynchronized指定
     getConverter() , detectConverter()
3)SyncronzedMapでWrapする
     protected Map converterCache = Collections.synchronizedMap(new HashMap());

----------------------------------------------------------------
スレッドダンプの一部(ほぼ同じThreadが9つある)
----------------------------------------------------------------
"p: thread-pool-1; w: 32" daemon prio=3 tid=0x000000010369fc00 nid=0xe5 runnable [0xffffffff6fff9000..0xffffffff6ffff6c0]
   java.lang.Thread.State: RUNNABLE
	at java.util.HashMap.get(HashMap.java:303)
	at org.seasar.extension.dxo.converter.impl.ConverterFactoryImpl.getConverter(ConverterFactoryImpl.java:106)
	at org.seasar.extension.dxo.command.impl.BeanToBeanDxoCommand.convertScalar(BeanToBeanDxoCommand.java:60)
	at org.seasar.extension.dxo.command.impl.AbstractDxoCommand$ListToListConvertsionHelper.convert(AbstractDxoCommand.java:286)
	at org.seasar.extension.dxo.command.impl.AbstractDxoCommand.execute(AbstractDxoCommand.java:78)
	at org.seasar.extension.dxo.DxoInterceptor.invoke(DxoInterceptor.java:57)



Seasar-user メーリングリストの案内