JBoss ASでコネクションクローズ漏れ検知
JBoss Advent Calendar 2011の10日目のエントリです。JBoss ASのデータソースその他のパラメータでStatementやResultSetのクローズ漏れをクローズする
JDBCのConnectionは通常サーブレットやEJBの内部でオープンされ、クローズされる、という形で利用されます。JBoss ASではこのConnectionのオープン処理をフックして記録しており、サーブレットやEJBを抜ける時に内部でオープンされたコネクションがきちんとクローズされているかどうかをチェックしています。この機能はサーブレットやEJBコンテナのプラグインレイヤで行っているため、例えばJMX上のスレッドや他のスレッド上ではこのConnectionもクローズ漏れチェックは機能しません。
$JBOSS_HOME/server/$PROFILE/deploy/jca-jboss-beans.xmlのCachedConnectionManager.debugにtrueが指定されている場合、Connectionもクローズ漏れチェックが有効です。falseを指定することで無効化できます。
実際にクローズ漏れが検出されると、"Closing a connection for you. Please close them yourself"というメッセージと共に、getConnection()をコールしたコードのスタックトレースが表示されます。
例えば、こんなJSPを書いてみます。このJSPではgetConnection()していますがそのまま放置してclose()を呼ばないままリクエスト処理を終了します。
(テスト目的でJSPを使ってスクリプトレットで書いていますが、良い子は無闇にJSPとか使わないようにしましょう)
<html xmlns="http://www.w3c.org/1999/xhtml" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xml:lang="en" lang="en"> <jsp:directive.page import="javax.sql.DataSource,javax.naming.InitialContext" /> <jsp:scriptlet> String name = "java:DefaultDS"; ((DataSource)new InitialContext().lookup(name)).getConnection(); </jsp:scriptlet> <body> <p>ok</p> </body> </html>
これをJBoss AS 6.1.0.Final上で実行してみるとConnectionのクローズ漏れを教えてくれます。
10:57:12,724 INFO [org.jboss.resource.connectionmanager.CachedConnectionManager] Closing a connection for you. Please close them yourself: org.jboss.resource.adapter.jdbc.jdk6.WrappedConnectionJDK6@150f4590: java.lang.Throwable: STACKTRACE at org.jboss.resource.connectionmanager.CachedConnectionManager.registerConnection(CachedConnectionManager.java:278) [:6.1.0.Final] at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:524) [:6.1.0.Final] at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:941) [:6.1.0.Final] at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:89) [:6.1.0.Final] at org.apache.jsp.index_jsp._jspService(index_jsp.java:64) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) [:6.1.0.Final] at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [:1.0.0.Final] at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:369) [:6.1.0.Final] at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:326) [:6.1.0.Final] at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:253) [:6.1.0.Final] at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [:1.0.0.Final]
JBoss AS 7.1.0.Beta1ではまだ同等の機能は実装されていないようです。