- PR -

Oracle JDBCドライバのメモリリークについて

投稿者投稿内容
未記入
会議室デビュー日: 2008/01/17
投稿数: 12
投稿日時: 2008-01-22 22:10
Oracle JDBCドライバはコネクションプーリングを使用している場合、Connectionをcloseしても、StatementとResultSetを明示的にcloseしないと、メモリリークの原因になると聞いた事がありますが、StatementとResultSetは必ず両方とも明示的にcloseしないといけないのでしょうか?
Statementのcloseだけでは不足でしょうか?
例えば、以下のような感じです。

public ArrayList getList(){
Connection con = null;
Statement stat = null;
ResultSet result = null;

ArrayList list = new ArrayList();

try{
con = getConnection(); // プーリングしているコネクションを取得
stat = con.createStatement();
result = stat.executeQuery("SELECT * FROM AA");

while(result.next()){
list.add(result.getString("A"));
}
}catch(Exception e){
return null;
}finally{
if(!stat.isClosed()){
stat.close();
}
if(!con.isClosed()){
con.close();
}
}

return list;
}

どなたか、情報をお持ちの方がいらっしゃいましたらご教示願います。
J2SE1.4、Oracle JDBC Driver 9.2.0です。
deanna
大ベテラン
会議室デビュー日: 2004/08/23
投稿数: 118
投稿日時: 2008-01-22 22:27
メモリリークになるという情報をどこから入手しましたか?
情報が正確なのか、信頼できるのかどうかはあなたの判断ですが、
こういう場で聞いた話をそのまま書くのはいかがなものか?

StatementとResultSetをクローズしなくてもいいと言う情報はどこからでしょう。
普通はちゃんとクローズしますけど。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-01-23 11:29
うろ覚えですが、ここ(@IT 会議室)で、ちょっと前(1〜2年ほど前?)にも、ほぼ似たような話題があったような気がします。が、どのスレッドかや、結論はどうだったか、はちょっと覚えていません。

Statement と ResultSet の関係を持つクラス構造は、JDBC に限らず、ADO などでも似たような感じですので、個人的には JDBC 以外も調べて見たいところです。
未記入
会議室デビュー日: 2008/01/17
投稿数: 12
投稿日時: 2008-01-23 22:29
お世話になります。

なるほど、似たような話題が過去にあったのですね。
探しては見たのですが見つける事ができなかったので・・・。
再度探してみたいと思います。

ちなみに情報源はこの辺です。
http://www.beasys.co.jp/cs/support_news/product_troubleshooting/Investigating_Out_of_Memory_Memory_Leak_Pattern.html

http://kvasir.skirnir.net/software/java/oracle_jdbc.html

http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/java.111/E05720-01/getsta.htm#i1006632
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-01-23 22:41
思い出しました。

件名:急にレスポンスが遅くなる
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10297&forum=12

です。4年前ですね。
私は、内容は良く理解できていないのですが、Statement, ResultSet, close, JDBC, Oracle といったキーワードが出てきています。
Kazuki
ぬし
会議室デビュー日: 2004/10/13
投稿数: 298
投稿日時: 2008-01-24 05:43
JDBCの仕様上はcloseを呼び出さなくても大丈夫とあっても、実装がそうなってるとは限らないのでcloseは呼んでおいたほうが確実です。

ConnectionPoolingを使用してる場合は、コネクションのcloseをしても、実際のDBとの接続は閉じないので、closeを呼び出してないStatementやResultSetのリソースが残っても不思議じゃないかもですね。
_________________
かずきのBlog http://blogs.wankuma.com/kazuki/
未記入
会議室デビュー日: 2008/01/17
投稿数: 12
投稿日時: 2008-01-24 21:47
お世話になります。

引用:

思い出しました。

件名:急にレスポンスが遅くなる
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=10297&forum=12

です。4年前ですね。
私は、内容は良く理解できていないのですが、Statement, ResultSet, close, JDBC, Oracle といったキーワードが出てきています。


そうですね。JDBCのメモリリークが話題になっていますね。
SUNのAPI上では、StatementをcloseするとResultSetを自動的にcloseする事になっているが、Oracle JDBCはStatementをcloseしてもResultSetを操作できてしまうと言うのは、結局はOracle JDBCではResultSetは自動的にcloseされないということなのでしょうね。
私も時間を見つけて検証してみたいと思います。

引用:

JDBCの仕様上はcloseを呼び出さなくても大丈夫とあっても、実装がそうなってるとは限らないのでcloseは呼んでおいたほうが確実です。

ConnectionPoolingを使用してる場合は、コネクションのcloseをしても、実際のDBとの接続は閉じないので、closeを呼び出してないStatementやResultSetのリソースが残っても不思議じゃないかもですね。


そうなんですよね。
私も自分でコーディングする時は、必ずStatementとResultSetの両方をcloseするのですが、今回は引き継いだシステムがStatementしかcloseされていなかったので、これで大丈夫なのかな、と不安になっていました。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2008-01-24 23:31
最近はデータソースを使う事が多いと思いますが、
その場合のConnection#close()はプールへの返却となります。
なので、最低限Statement#close()を呼び出さないと、
ずっと閉じられないという可能性もあります。

最近はPreparedStatementをキャッシュするフレームワークもありますので、
ResultSet#closeの呼び出しも必須でしょう。

これらのメソッドはインターフェイスのメソッドなので、
どういう内部実装になっているのか見えないわけですが、
その分余計に流儀を守った実装が必要です。

スキルアップ/キャリアアップ(JOB@IT)