人類みんなごくつぶし

2010-09-18

[]MemoryLeakProtectionとJDBC 21:20

Tomcat上で、昔は文句言われずに動いてたWebアプリが、最近動かしたら、リロード時に怒られるようになった。こんなメッセージがでる。

致命的: The web application [/hogehoge] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.


ぐぐってみると、内臓DBCPのバグだから、君は悪くない!ほっとけ!っていうのがあって、ちょっとホッとしたが

http://stackoverflow.com/questions/3320400/jdbc-driver-unregisted-when-the-web-application-stops

Tomcat ships with a memory leak detection feature, which in turn can lead to this kind of warning messages. This particular message is caused by Tomcat's builtin DBCP not deregistering drivers properly on close. See also bug DBCP-322. This message is purely informal, Tomcat has already taken the memory leak prevention action accordingly.


でも、自分アプリ、DataSoruceじゃなくて、直JDBC(自分Class.forName→内部でDriverManager.registerDriverしてる)だし、内臓DBCPのせいにするのは違うなぁ。


で、もうちょっと探してて

Tomcat6.0.24くらいから、メモリリークとかのチェック機能が追加されたらしい


http://wiki.apache.org/tomcat/MemoryLeakProtection

JDBC driver registration

If a webapp contains a JDBC driver (e.g. in WEB-INF/lib), the driver will be registered with the DriverManager when it is first used. When the application is stopped, the driver should be deregistered with DriverManager to avoid a classloader leak. Since applications usually forget this, tomcat helps by deregistering the driver.


JDBCでつないでる場合は、Webアプリ側にunregisterDriverする責任があるのかぁ

めんどくさいなぁ

(普通お仕事アプリとかなら別に面倒じゃないと思うが、

ちょこっとサンプルWEBアプリなどの場合、相対的に面倒)


Webアプリ閉じるタイミング、例えば

ServletContextListener#contextDestroyedとかで

こんな感じのコード呼び出すんでいいのかな。

Driver driver = DriverManager.getDriver(URL);
DriverManager.deregisterDriver(driver);

汎用的にするならこんな感じか

Enumeration<Driver> drivers = DriverManager.getDrivers();
while( drivers.hasMoreElements() ){
    Driver driver = drivers.nextElement();
    DriverManager.deregisterDriver(driver);
}

しかし、わざわざSEVERE!とか警告するぐらいのなら、

この汎用的なやつTomcat勝手に呼んでくれればいいと思うんだけど


何か長年つれそった嫁が突然、ドアをバタンとしめるのヤメてとか言い出した感じだ

リンク元