HttpURLConnectionを使用する場合、「取得」して使用しない場合はInputStreamを閉じる必要がありますか?
つまり、これは安全ですか?
HttpURLConnection conn = (HttpURLConnection) uri.getURI().toURL().openConnection();
conn.connect();
// check for content type I don't care about
if (conn.getContentType.equals("image/gif") return;
// get stream and read from it
InputStream is = conn.getInputStream();
try {
// read from is
} finally {
is.close();
}
第二に、すべてのコンテンツが完全に読み込まれる前にInputStream を閉じることは安全ですか?
基礎となるソケットをESTABLISHEDまたはCLOSE_WAIT状態のままにするリスクはありますか?
すべてのコンテンツが読み込まれる前にInputStreamを閉じても安全ですか?
基になるTCP接続がキャッシュされるようにするために、入力ストリームのすべてのデータを閉じる前に読み取る必要があります。最新のJavaでは必要ではないことを読みました接続の再利用のために応答全体を読み取ることが常に義務付けられています。
この投稿を確認してください: Java6でキープアライブ
http://docs.Oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html およびOpenJDKソースコードによると。
(_keepAlive == true
_の場合)
クライアントがHttpURLConnection.getInputSteam().close()
を呼び出した場合、後でHttpURLConnection.disconnect()
を呼び出すと、Socket
を閉じませんNOT。つまり、Socket
は再利用されます(キャッシュされます)
クライアントがclose()
を呼び出さない場合、disconnect()
を呼び出すと、InputStream
が閉じられ、Socket
が閉じられます。
したがって、Socket
を再利用するには、InputStream.close()
を呼び出すだけです。 HttpURLConnection.disconnect()
を呼び出さないでください。
キープアライブキャッシュに関する情報を次に示します。この情報はすべて、Java 6に関連していますが、多くの以前および以降のバージョンでもおそらく正確です。
私が言えることから、コードは次のように要約されます:
このロジックは、 Sun.net.www.http.HttpClient (「parseHTTPHeader」メソッド内)の725行目付近と Sun.net。 www.http.KeepAliveCache (「put」メソッド内)。
そのため、タイムアウト期間を制御するには2つの方法があります。
内部JDKクラスを再コンパイルせずに、明らかに任意の5秒のデフォルトを変更することは可能だと思うでしょうが、そうではありません。 bug は2005年にこの機能を要求するために提出されましたが、Sunはそれを提供することを拒否しました。
接続を確実に閉じたい場合は、conn.disconnect()
を呼び出す必要があります。
開いた接続は、HTTP 1.1接続キープアライブ機能( HTTP Persistent Connections とも呼ばれます)が原因です。サーバーがHTTP 1.1をサポートし、応答ヘッダーでConnection: close
を送信しない場合Javaは、入力ストリームを閉じたときに、下にあるTCP接続をすぐに閉じません。代わりに、サーバーを開いたままにして、同じサーバーへの次のHTTP要求に再利用しようとします。
この動作がまったく必要ない場合は、システムプロパティhttp.keepAlive
をfalseに設定できます。
System.setProperty("http.keepAlive","false");
HTTPリクエストが失敗した場合(200以外)、エラーストリームを閉じる必要もあります。
try {
...
}
catch (IOException e) {
connection.getErrorStream().close();
}
これを行わないと、200を返さないリクエスト(タイムアウトなど)はすべて1つのソケットをリークします。
HttpURLConnectionを使用する場合、「取得」して使用しない場合はInputStreamを閉じる必要がありますか?
はい、常に閉じている必要があります。
つまり、これは安全ですか?
100%ではなく、NPEを取得するリスクがあります。より安全です:
InputStream is = null;
try {
is = conn.getInputStream()
// read from is
} finally {
if (is != null) {
is.close();
}
}