MemoryLeakProtectionとJDBC2
http://d.hatena.ne.jp/muimy/20100918/1284812424
のつづき
どうも、WEB-INF/libにJDBCドライバ置かずに、Tomcatのlibに置いたら、怒られないようだ
汎用的なやつをTomcatが勝手に呼んでくれないのは、クラスローダーがらみの問題ぽい。
registerDriverするのとunregisterDriverするのは同じクラスローダーである必要があるとか
Tomcatのソースちょっと追ってみたが、警告を出しているのは、
TomcatのWebappClassLoader#clearReferencesJdbcメソッド内の以下の部分
for (String name : driverNames) { log.error(sm.getString("webappClassLoader.clearJbdc", contextName, name)); }
で、その前にJdbcLeakPrevention#clearJdbcDriverRegistrations を呼び出していて、中でやってるのがこれ
public class JdbcLeakPrevention { public ListclearJdbcDriverRegistrations() throws SQLException { List driverNames = new ArrayList (); // This will list all drivers visible to this class loader Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); // Only unload the drivers this web app loaded if (driver.getClass().getClassLoader() != this.getClass().getClassLoader()) { continue; } driverNames.add(driver.getClass().getCanonicalName()); DriverManager.deregisterDriver(driver); } return driverNames; } }
JDBCドライバをロードしたクラスローダーと
JdbcLeakPreventionクラスをロードしたクラスローダー(StandardClassLoader?)が同じだったらunregisterDriverして、そうでなかったら、リストにつっこんで返す。
で、返されたドライバーが先のエラー出力の対象になる
WEB-INF/libにおいたJARをロードするクラスローダーってデフォでWebappClassLoaderなんだから、WebappClassLoaderでロードされたやつもunregisterDriverしてくれてもいいような気がするけど。
参考
http://d.hatena.ne.jp/tksmd/20100717#p1
http://d.hatena.ne.jp/TAKESHI/20100217/1266417114
http://d.hatena.ne.jp/c9katayama/20100715/1279162138