2015-10-22 28 views
7

ストリームをクローズしていない場合は、ストリームをいつ閉じるかを知りたいです。これは私の言いたいことですが、ストリームの参照の範囲がもうなくなると、ストリームは閉じられますか?ストリームはいつ手動で閉じられないのですか?

次のサンプルシナリオを検討してください。ここで

Class A{ 
InputStream in; 
OutputStream out; 
A(){ 
    // Initialize and create the streams. 
} 
... 
} 
Class B{ 
public void myMethod(){ 
A a = new A(); 
System.out.println("End of my method.") 
} 
... 
} 

、私はストリームで行わいたら、私はmyMethod()が、今度はプロセスが、終了しないと他の操作とに行くのプログラムを終了しています。

ストリームを閉じなかった。クラスAへの参照のスコープが終了すると自動的に閉じられますか? (すなわち、myMethod()が終了すると)? GCはそれを処理しますか?また、プロセスが終了するとストリームがクローズされ、システムは他のプロセス用に保持されているすべてのリソースを解放することも読んでいます。ストリームが開いているかどうかはどうすれば確認できますか? Javaのコマンドやオプションがありますか?

ご協力いただきましてありがとうございます。

+0

「finally」ブロック(またはtry-with-resources)ですべてのストリーム(およびCloseables一般)を閉じる必要があります –

+0

この時点で、私は私の椅子に座って、私は試しています私が開いたすべてのJavaストリームを覚えておいて、それらが自動的に範囲外に閉じ込められたと仮定しました。過去15年間。それから、私は起き上がり、「C++あなたをとても愛している」と叫びます。 – Chameleon

答えて

10

私は、JVMの仕様がそのことについて何ら保証していないと思います。あなたは本当にfinallyこれらのリソースを閉じることになっています。

オペレーティングシステムは、メモリ、ファイルハンドル、ネットワークソケットを含むすべてのリソースを解放します。

開いているファイルとストリームについて確認するOS機能があります(lsofなど)。

+1

はい、私は 'finally'ブロックで閉じていますが、好奇心から尋ねました。しかし、これを世話するようにGCを設定する必要はないと思いませんか?参照のスコープが終了すると、メモリとともに参照されるすべてのストリームがガベージコレクションされる必要があるからです。ではない? –

+0

はい、GCが最終的に発生します。しかし、タイムリーであることが保証されているわけではなく、ファイナライザの実行が完全に保証されているわけではありません(ストリームを閉じる)。スタンスは、開発者はそれを世話することになっているということです。 – Thilo

0

これはプログラマーの間違いであり、プログラミングの面では問題があります。基礎となるデータソースによっては、決して閉じることはなく、リークが発生する可能性があります。リソースが終了したら、finallyブロックでリソースをクローズするか、Java 7以上のリソースでtryを使用して、例外がスローされてもクローズされていることを確認する必要があります。

InputStream in; 
OutputStream out; 
try { 
    // Do your stuff with the streams 
} finally { 
    if (in != null) { 
     in.close(); 
    } 
    if (out != null) { 
     out.close(); 
    } 
} 
4

プロセスtermiantesが、しかし、それはお勧めかのベストプラクティスではありませんときにそれを手動でclossingされていない場合は、すべてのアンマネージリソースを解放します。ストリームが終了したら、ストリームを閉じてください。

より良いとストリームを管理する方法を提案したが、このようなリソースオプションを指定してみてください使用することです:

try (InputStream input = new FileInputStream(...); 
    Reader reader = new InputStreamReader(input, ...)) { 
    ... 
} 

私はストリームを閉じませんでした。クラスAへの参照の スコープが終了すると自動的に閉じられますか?

いいえ自動的に閉じません。フォローする

良いの参照です:

Better Resource Management with Java SE 7: Beyond Syntactic Sugar

2

FileInputStreamの場合は、ストリームがガベージコレクトされたときにリソースを解放しますfinalize()方法があります。

あなたはそうすることはできません。それはちょうどFileInputStreamのことです。一方、SocketInputStreamfinalize()を明示的に無効にして、リソースを閉じるためにSocketに依存します(Socketにはfinalize()メソッドがありません)。

0

Java 7では、tryステートメントに1つ以上の "リソース"を作成できます。 「リソース」は、java.lang.AutoCloseableインタフェースを実装するものです。このリソースは自動的に閉じられ、tryブロックの終わりになります。 tryブロックは、FileInputStreamのが自動的に閉じられます終了すると

あなたは

プライベートの静的な無効printFileJava7(詳細はthisjava docを見ることができますが)はIOException {

try(FileInputStream input = new FileInputStream("file.txt")) { 

    int data = input.read(); 
    while(data != -1){ 
     System.out.print((char) data); 
     data = input.read(); 
    } 
} 

}

をスローします。これは、FileInputStreamがJavaインタフェースjava.lang.AutoCloseableを実装しているために可能です。このインタフェースを実装するすべてのクラスは、try-with-resources構造内で使用できます。

1

JVMが実行されている限り、リソースがクローズされる保証はありません。提案された実装は非常に危険です。

私は何を提案しますか? クラスAをCloseableにして、JavaのtryResourceClose-Statementを使用します。 例はここにあります。 https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

tryブロックを離れると、リソースを閉じることができます。

ストリーム自体は、通常、ストリームが開いているかどうかわかりません。 しかし、あなたのクラスAは、ストリームが閉じられたかどうかを追跡することができます。

関連する問題