- - PR -
FileInputStreamのcloseし忘れは、メモリーリーク?
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-11-26 22:28
いつもお世話になります。tomomoと言います。
初めて投稿します。よろしくお願いします。 今、次のようなコードを書きました。 1 import java.io.*; 2 import java.util.Properties; 3 4 public class FileInputSreamNotCloseTest { 5 6 private Properties property; 7 8 public FileInputSreamNotCloseTest() {} 9 10 public void createPropertiesFile(File f) 11 throws IOException,FileNotFoundException 12 { 13 if ( f.exists()==false ) f.createNewFile(); 14 this.property = new Properties(); 15 this.property.load(new FileInputStream(f)); 16 } 17 18 public static void main(String[] args) { 19 try { 20 for(int i=0; i<100; i++){ 21 File file = new File("C:\\temp\\test.txt"); 22 if( file.exists() ) System.out.println(i+"回目のstart:" + file.delete()); 23 24 FileInputSreamNotCloseTest f = new FileInputSreamNotCloseTest(); 25 f.createPropertiesFile(file); 26 27 if( file.exists() ) System.out.println(i+"回目のend:" + file.delete()); 28 } 29 } catch (Exception e) { 30 e.printStackTrace(); 31 } 32 } 33 } 34 このコードを実行すると、22行目と27行目のところで、ファイルの削 除がされない事実がわかりました。 何故か調査したところ、15行目のnew FileInputStream(f)で生成した FileInputStreamオブジェクトをcloseしていないため、ずーと開いた 状態?になっていたので、delete()されない事がわかりました。 15行目を FileInputStream fis = new FileInputStream(f); this.property.load(fis); fis.close(); これに置き換えたら、ファイルが削除されるようになりました。 前置きが長かったですが、ここからが本題なのです。 上記のようなコードの状態(FileInputStream#close()を実行しない状 態)の時ですが、new したFileInputStreamオブジェクトは、いつかGC の対象になるものなのでしょうか? それとも、メモリリークになり、いつかプロセスがダウンしてしまうの でしょうか? closeはしないといけないとは思いますが、closeをし忘れた場合、java VMとして、どうなるのかが知りたいです。 すみませんが、よろしくお願いします。 [ メッセージ編集済み 編集者: tomomo 編集日時 2004-11-26 22:29 ] [ メッセージ編集済み 編集者: tomomo 編集日時 2004-11-26 22:29 ] | ||||||||
|
投稿日時: 2004-11-26 23:22
unibon です。こんにちわ。
はい、"いつか"はなります(なにかメモリーを消費するコードを追加すると、"いつか" GC が起きて FileInputStream のインスタンスが解放されることが分かります)。 また、 http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/io/FileInputStream.html#finalize() の仕様により、FileInputStream クラスの finalize メソッドの中では close されることが保証されています。 これらの2つのことから、長期的にはメモリーリークにはならないと結論できます。 ただし、短期的(GC が動くまでの間)はメモリーリークです。ファイルハンドルのリソースの分だけメモリーが無駄に使われています。したがって、finalize での close に頼ることは、やっぱり避けるべきです。 | ||||||||
|
投稿日時: 2004-11-29 10:24
unibonさん。こんにちは。
勉強になりました。 使ったものは後片付けする事を忘れないように 心がけます。ありがとうございました。 | ||||||||
|
投稿日時: 2004-11-29 10:31
ガベージコレクションの対象となっているものを「メモリリーク」と呼ぶかどうかは微妙(っていうか正確には違う)ですが、close()するべきですね。
close()漏れがあるとファイルハンドラ(Windows)やファイルデスクリプタ(Unix)が枯渇して新規にファイルをオープンできなくなったりします。 大抵 too many open files とかいうメッセージと共に IOException が発生します。 ・BEA Troubleshooting Guidance > Support Diagnostic Patterns > Too Many Open Files http://support.bea.com/support_news/product_troubleshooting/Too_Many_Open_Files_Pattern.html | ||||||||
|
投稿日時: 2004-11-29 14:44
こんにちは、Wataです。
について、 ストリームのクローズはfinallyブロックを使って行うようにしてください。
こうしておけば、loadメソッドがIOExceptionを投げた場合でも確実にclose()を呼び出せます。 基本イディオムとして、覚えておくといいですよ。 |
1