データベース接続の解放など、終了処理(後始末)をいろいろと書きたいケースは多々あります。
Javaには、Objectクラスにfinalizeメソッドが用意されています。
一見、finalizeメソッドをオーバーライドして、終了処理を書いておけば良さそうですが、そうではありません。
finalizeメソッドをオーバーライドした処理は、とりあえず、“正常”にインスタンスが”ガーベージコレクションされるとき”に、(JVMがてきとーな努力をして)呼び出されます。
※仮に呼んでくれても、ガーベージコレクションされるときなので、すぐかもしれないし、翌日かもしれないし、とにかく期待できるタイミングではありません。
よって、finalizeメソッドをオーバーライドして書かれた処理は、処理が終わって、インスタンスが消えようとするとき(=いつか)に呼ばれるかもしれないし、呼ばれないかもしれませんw
つまるところ、finalizeメソッドをオーバーライドして、何らかの終了処理をするようなコードは、書いてはいけません。
処理が終わったときに、何かしたいのであれば、finally節を使いましょう♪
ダメな例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class FinalizeTest { public void execute() { //データベース接続 openDatabase(); //SQL発行等の処理 ・・・ } @Override protected void finalize() throws Throwable { //データベース接続の解放 closeDatabase(); //NG } } |
よって、他のスレッドで同様の処理があると、コネクションプールの取得で待ち続ける可能性があります。
修正例
finalizeメソッドをオーバーライドするのではなく、処理が終わったら、接続を解放するのが基本です。
また、例外等が発生しても接続を解放するように、finally節で実施すると確実です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class FinalizeTest { public void execute() { try { //データベース接続 openDatabase(); //SQL発行等・・・ ・・・ }finally { //データベース接続の解放 closeDatabase(); //OK } } } |