Подтвердить что ты не робот

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();
}

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

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

4b9b3361

Ответ 1

При обновлении до 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();
}

Ответ 2

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

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

Ответ 3

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

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