[Seasar-user:21031] [S2DBCP]minPoolSizeを設定するとNullPointerExceptionが発生する

koba168 [E-MAIL ADDRESS DELETED]
2011年 9月 26日 (月) 15:57:34 JST


お世話になります。小林と申します。

S2DBCPのコネクションプーリング機能でNullPointerExceptionが発生するケース
が見つかりましたので報告いたします。


環境:
Seasar2 2.4.44

jdbc.dicon:

<component name="connectionPool"
	class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
	<property name="timeout">60</property>
	<property name="maxPoolSize">10</property>
	<property name="minPoolSize">1</property>
	<property name="allowLocalTx">true</property>
	<destroyMethod name="close"/>
</component>


スタックトレース:

java.lang.NullPointerException
	at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkOutFreePool(ConnectionPoolImpl.java:400)
	at org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkOut(ConnectionPoolImpl.java:364)
	at org.seasar.extension.dbcp.impl.DataSourceImpl.getConnection(DataSourceImpl.java:59)
	at org.seasar.doma.internal.jdbc.util.JdbcUtil.getConnection(JdbcUtil.java:40)
	at org.seasar.doma.internal.jdbc.command.SelectCommand.execute(SelectCommand.java:53)
	... 以下省略 ...



再現させる手順ですがminPoolSizeに1以上の値を設定した状態で

1. プールされたコネクションがtimeoutで指定された時間を経過
2. expired処理実行。プールされたコネクション数がminPoolSizeを下回りプールから削除しない
3. そのコネクションをプールから取得して使用する

の流れでNullPointerExceptionが発生します。


ソースを確認したところ以下のexpiredの処理が問題だと思われます。

org.seasar.extension.dbcp.impl.ConnectionPoolImpl$FreeItem#expired()

        public void expired() {
            synchronized (ConnectionPoolImpl.this) {
                if (freePool.size() > minPoolSize) {
                    freePool.remove(this);
                }
            }
            synchronized (this) {
                if (timeoutTask_ != null) {
                    timeoutTask_.cancel();
                    timeoutTask_ = null;
                }
                if (connectionWrapper_ != null) {
                    connectionWrapper_.closeReally();
                    connectionWrapper_ = null;
                }
            }
        }


freePoolのサイズがminPoolSizeを下回る場合に、freePool.remove(FreeItem)は呼ばれないが
FreeItemの内部変数として保持しているconnectionWrapper_については必ずクローズしてnullを設定するので
次回、このFreeItemがfreePoolリストから取り出されてconnectionWrapper_が使用されるときに
NullPointerExceptionが発生する。


とりあえずこの部分を修正してこの問題は回避しています。
よろしくお願いいたします。


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