OkHttp: избегайте утечки предупреждение соединения

я использую 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();
}

мое приложение интенсивно использует сеть, и все же это предупреждение появляется часто. Я никогда не наблюдал никаких проблем, вызванных этой предполагаемой утечкой, но я все равно хотел бы понять если и что Я делаю неправильно.

может ли кто-нибудь пролить свет на это?

3 ответов


обновившись до 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();
}

Как упоминалось в других ответах, вы должны закрыть ответ. Немного более чистым подходом было бы объявить ResponseBody в блоке try, так что он будет автоматически закрыт.

try(ResponseBody body = ....){
....
}

вы должны закрыть body () попробуйте ниже code

ResponseBody body = resp.body();
try {
  ...
} finally {
 body.close();
}