私はOkHttp 3を使用していますが、接続警告が漏れ続けています:
_WARNING: A connection to https://help.helpling.com/ was leaked. Did you forget to close a response body?
Jul 14, 2016 6:57:09 PM okhttp3.ConnectionPool pruneAndGetAllocationCount
_
ResponseBody
を取得するたびに、次の方法で.string()
を呼び出して、おそらくストリームを閉じます。または、finally
ブロックで明示的に閉じます。
_ResponseBody responseBody = response.body();
try (Reader responseReader = responseBody.charStream()) {
...
}
finally {
responseBody.close();
}
_
私のアプリケーションはネットワークを多用していますが、その警告は頻繁に表示されます。この推定リークによって引き起こされる問題は一度も見たことがありませんが、まだifおよびwhat間違っていることを理解したいと思います。
誰もこれに光を当てることができますか?
OkHttp 3.7にアップグレードすることで、Eclipseは潜在的なリソースリークの警告を開始しました。私が書いたこの方法に問題があることがわかりました:
_public static Response getResponse(HttpUrl url, OkHttpClient client) throws IOException {
Builder request = new Request.Builder().url(url);
Response response = client.newCall(request.build()).execute();
if (!response.isSuccessful()) {
boolean repeatRequest = handleHttpError(response);
if (repeatRequest)
return getResponse(url, client, etag);
else
throw new IOException(String.format("Cannot get successful response for url %s", url));
}
return response;
}
_
常にgetResponse(url, client).body().string()
を呼び出すことで、ストリームが自動的に閉じると想定しました。ただし、応答が失敗すると、.string()
の実行前に例外が発生するため、ストリームは開いたままになります。
応答が失敗した場合に明示的なクローズを追加すると、問題が解決しました。
_if (!response.isSuccessful()) {
boolean repeatRequest = handleHttpError(response);
response.close();
}
_
他の回答で述べたように、応答を閉じる必要があります。少し簡潔な方法は、tryブロックでResponseBody
を宣言して、自動的に閉じるようにすることです。
try(ResponseBody body = ....){
....
}