web-dev-qa-db-fra.com

OkHttp: éviter l'avertissement de fuite de connexion

J'utilise OkHttp 3 et je reçois toujours des avertissements de connexion perdus:

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

Chaque fois que j'obtiens un ResponseBody, j'appelle .string() qui ferme soi-disant le flux, ou je le ferme explicitement dans un bloc finally, de la manière suivante:

ResponseBody responseBody = response.body();
try (Reader responseReader = responseBody.charStream()) {
    ...
}
finally {
    responseBody.close();
}

Mon application utilise intensivement le réseau, et pourtant cet avertissement apparaît fréquemment. Je n'ai jamais observé de problème causé par cette fuite présumée, mais je voudrais quand même comprendre si et quoi je me trompe.

Quelqu'un pourrait-il nous éclairer là-dessus?

27
Alphaaa

En effectuant une mise à niveau vers OkHttp 3.7, Eclipse a commencé à m'avertir de fuites potentielles de ressources. J'ai trouvé mon problème dans cette méthode, j'ai écrit:

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

J'ai supposé qu'en appelant toujours getResponse(url, client).body().string() le flux se fermerait automatiquement. Mais, chaque fois qu'une réponse échoue, une exception se déclenche avant l'exécution de .string(), ainsi le flux reste ouvert.

L'ajout d'une fermeture explicite en cas de réponse infructueuse a résolu le problème.

if (!response.isSuccessful()) {
    boolean repeatRequest = handleHttpError(response);
    response.close();
}
12
Alphaaa

Comme mentionné dans les autres réponses, vous devez fermer la réponse. Une approche légèrement plus propre consisterait à déclarer le ResponseBody dans le bloc try, afin qu'il soit automatiquement fermé.

try(ResponseBody body = ....){
....
}
10
Corrigan Johnson