2013-04-12 8 views
26

私はEntityUtils.consume(httpEntity);に出くわしました。本当に何ができるのか分かりません。例えば著者はなぜEntityUtils.consume(httpEntity);を使用しましたか?

finallyブロックが接続を閉じ、ガベージコレクタがhttpEntityの世話をするのに、なぜ著者はEntityUtils.consume(httpEntity);に入れなかった

try { 

    //... some code 

    HttpEntity httpEntity = httpResponse.getEntity(); 
    BufferedReader br = new BufferedReader(new InputStreamReader(http.Entity.getContent())); 
    String line; 
    while ((line = br.readLine())!= null) { 
     System.out.println(line); 
    } 
    EntityUtils.consume(httpEntity); 
} catch (Exception e) { 
    //code 
} finally { 
    httpClient.getConnectionManager().shutdown(); 
} 

答えて

31

実際には、「良い市民」であること(そして実際にはHTTPClientインターフェイスの契約を知っている)にまで沸きます。 EntityUtils.consumeは、httpEntityが保持するすべてのリソースを解放します。基本的なストリームを解放し、Connectionオブジェクトをそのプールに戻すことを意味します(接続マネージャがマルチスレッドの場合)。または接続マネージャを解放して次の要求を処理できます。

entityを消費しない場合は、最終的に「接続マネージャをシャットダウンする」という意味になります。プールに返送されていない保留中のストリーム/接続をクローズしますか?私はそれが契約上それを行うかどうかはわかりません(ただし実装上は私はそう思う)。そうでなければ、システムリソース(ソケットなど)が漏れている可能性があります。 Entityオブジェクトの可能なファイナライゼーション方法によっては、(実行されたとしても)Entityオブジェクトのリソースを解放することができます。

シャットダウン時にConnectionManagerが実際にすべての保留中のリソースを正常に閉じるとします。あなたはまだエンティティを消費する必要がありますか?今から1ヶ月後に誰かがあなたのコードを修正し、同じtry/finallyブロックで2回目のHTTP呼び出しを行い、リソースを解放していないためにそうすることができないため、はいと言います(ifあなたはクライアントが単一の接続プールにあり、最初の接続を解放しないと2番目の呼び出しが失敗します)。

私の主張は次のとおりです。エンティティはリソースであり、必要がない場合はリソースを解放する必要があります。後であなたのためにそれらを解放するために他人を数えることは、将来あなたを傷つけるかもしれません。元の著者は、これらの行に沿って考えるかもしれません。

あなたが書いた実装は実際にはリーダーを基本ストリームの終わりまで消費するので、消費呼び出しは実際には何もしませんが、これは実装の詳細です(私の頭の上から、レスポンスストリームが完全に読み込まれると、接続オブジェクトはHTTPクライアントのプールに自動的に解放/返されます)。 APIが提供するResponseHandlerのテクニックを使用すると、このConsumeロジックもすべて抽象化されます。 最後に、APIはresponse.getEntityが決してnullを返さないことを保証しないので、NullPointerExceptionを避けるようにチェックする必要があります。

関連する問題