2016-07-14 11 views
8

Ich verwende OkHttp 3, und ich werde immer Verbindung Warnungen durchgesickert:OkHttp: durchgesickert Verbindung vermeiden Warnung

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 

Jedesmal, wenn ich einen ResponseBody, ich entweder Anruf .string(), die angeblich den Stream für mich schließt, oder ich schließen sie es explizit in einem finally Block, auf folgende Weise:

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

Meine Anwendung intensive Nutzung des Netzes macht, und doch häufig diese Warnung angezeigt wird. Ich habe nie ein Problem durch dieses vermeintliche Leck beobachtet, aber ich würde immer noch gerne verstehen, wenn und was Ich mache falsch.

Könnte irgendjemand etwas Licht darauf werfen?

Antwort

1

Mit dem Upgrade auf OkHttp 3.7 hat Eclipse mich vor möglichen Ressourcenlecks gewarnt. Ich fand mein Problem bei dieser Methode zu sein, schrieb ich:

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

ich davon aus, dass durch immer getResponse(url, client).body().string() Aufruf der Strom automatisch schließen würde. Aber immer wenn eine Antwort nicht erfolgreich war, würde vor der Ausführung von .string() eine Ausnahme ausgelöst werden, daher würde der Stream geöffnet bleiben.

Das Hinzufügen eines expliziten Abschlusses im Falle einer nicht erfolgreichen Antwort löste das Problem.

if (!response.isSuccessful()) { 
    boolean repeatRequest = handleHttpError(response); 
    response.close(); 
} 
-1

Sie den Körper zu schließen haben() versuchen, unter Code

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

Wenn Sie meine Frage gelesen, hätten Sie gesehen, dass ich schon genau tue dies ... – Alphaaa

+0

dieses Problem folgen Sie erhalten Sie antworten, da an diesem https keine vollständige Code ist: // GitHub. com/square/okhttp/issues/2311 –

+0

Vielen Dank für den Link, aber das Problem dort war nur, weil das Plakat den Körper überhaupt nicht für nicht-200 Antworten geschlossen hat. Hier mit dem 'finally' Block sollte ich alle Fälle erfassen. – Alphaaa

1

Wie in den anderen Antworten erwähnt, müssen Sie die Antwort schließen. Ein etwas saubererer Ansatz wäre, die ResponseBody im try-Block zu deklarieren, so dass sie automatisch geschlossen wird.

+0

Für einige könnte es etwas netter sein, die Antwort direkt zu schließen als die Antwort direkt. Das Schließen der Response schließt also das zugrunde liegende ResponseBody ... für meine Anwendungsfälle ist das Schließen von Response ein wenig besser. –

+0

Ich konnte keinen Try-with-Resources-Ansatz verwenden, weil meine Methode die 'Response' -Instanz zurückgeben musste, um von einer anderen Methode gelesen zu werden, wenn sie erfolgreich war (siehe meine eigene Antwort). – Alphaaa