2017-08-02 2 views
1

私はいくつかの同様の質問を見つけましたが、私はまだ私の質問に対する答えを見つけることができません。インライン作成されたInputStreamはGCによって自動的に閉じられますか?

私は外側のストリームを閉じるだけで十分であり、それはラインで作成された内側のストリームを閉じることを知っています。

BufferedInputStream br = new BufferedInputStream(new FileInputStream(file)); 
br.close(); 

は、次の例に考えてみましょう

Properties props = new Properties(); 
props.load(new FileInputStream(configPath)); 

FileInputStreamを変数に代入してから(または試み-とリソースの構造を持つ)またはJava GCは右props.load()メソッドの後に自動的に閉じます明示的に閉じる必要があります呼び出しは、リソースへの参照がないためですか?

+1

「GB」とはどういう意味ですか? – biziclop

+1

リソースの解放を行うためにガベージコレクタに頼るべきではありません。あなたの質問に対する正解は「_itかもしれない、そうでないかもしれない」です。 –

+0

@MProkhorovのコメントについては、ガベージコレクタがその作業を行うときには保証されません。原則として無期限に仕事を延期することができます。つまり、リソースは無期限に割り当てられます。 GCに頼るのではなく、リソースを明示的に閉じます。 – Jesper

答えて

6

Javadocは

指定されたストリームはこのメソッドから復帰したあとも開いたままであることを述べています。

したがって、クリーンなコードを書きたい場合は、自分で終了する必要があります。 GCは最後にを閉じます。の場合はストリームのfinalize()メソッド(下記参照)を呼び出すまで戻りますが、shouldn't rely on thatです。

必ずリソースを閉じてください。これが確実な唯一の方法です。

/** 
* Ensures that the <code>close</code> method of this file input stream is 
* called when there are no more references to it. 
* 
* @exception IOException if an I/O error occurs. 
* @see  java.io.FileInputStream#close() 
*/ 
protected void finalize() throws IOException { 
    if ((fd != null) && (fd != FileDescriptor.in)) { 
     /* if fd is shared, the references in FileDescriptor 
     * will ensure that finalizer is only called when 
     * safe to do so. All references using the fd have 
     * become unreachable. We can call close() 
     */ 
     close(); 
    } 
} 
3

ストリームの構築とclose()コール間の操作が例外をスローした場合終値は、発生しませんよう

BufferedInputStream br = new BufferedInputStream(new FileInputStream(file)); 
// you likely insert actual operations on br here 
br.close(); 

のようなコードを使用して、強くお勧めしますことを強調しなければなりません。

あなたは「資源としてみてください」ではなく構築使用する必要があります。

try(BufferedInputStream br = new BufferedInputStream(new FileInputStream(file))) { 
    // your actual operations on br here 
} 

これはclose()は例外がtry体内で発生した場合でも呼び出されることを保証します。しかし、このコードはBufferedInputStreamclose()メソッドがFileInputStreamclose()メソッドを呼び出すという既知の事実に依存しますが、BufferedInputStreamの構築が完了するまでは発生しません。 BufferedInputStreamのコンストラクタが例外をスローすると、close()を呼び出すオブジェクトがないので、close()メソッドは呼び出されません。

本当に安全ソリューションは、BufferedInputStreamのコンストラクタが例外をスローした場合でもFileInputStreamを閉じ

try(FileInputStream fis = new FileInputStream(file); 
    BufferedInputStream br = new BufferedInputStream(fis)) { 
    // your actual operations on br here 
} 

です。このコンストラクタで間違っている可能性があるのは、OutOfMemoryErrorを投げる可能性のあるバッファ割り当てであり、その場合は深刻な問題になります。

しかしObjectInputStreamのコンストラクタは、すでにヘッダを読み込むので

try(FileInputStream fis = new FileInputStream(file); 
    ObjectInputStream ois = new ObjectInputStream(fis)) { 
    // your actual operations on ois here 
} 

のような例を考えて、IOException Sは、例外を引き起こすことになる、また、ヘッダーは無効である可能性があります、スローされる可能性があります。したがって、間違っていて、そのような場合でも基礎となるFileInputStreamが正しく閉じられていることを保証するためには、さらに多くのことが重要です。

関連する問題