2016-07-14 130 views
8

我使用OkHttp 3,我不斷收到泄露連接警告:OkHttp:避免泄露連接警告

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

我的應用使得大量使用網絡的,然而這一警告經常出現。我從來沒有觀察到這個假定的泄漏造成的任何問題,但我仍然想了解如果什麼我做錯了。

任何人都可以對此有所瞭解嗎?

回答

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

你有收身()試試下面的代碼

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

如果你讀了我的問題,你會看到,我已經這樣做正是這一點... – Alphaaa

+0

遵循這個問題,你會得到你的答案,有對 HTTPS沒有全碼:// github上。 com/square/okhttp/issues/2311 –

+0

謝謝你的鏈接,但是那裏的問題只是因爲海報沒有關閉非200響應的身體。在這裏用'finally'塊,我應該抓住所有的情況。 – Alphaaa

1

正如在其他的答案中提到,你必須關閉的響應。稍微簡潔的方法是在try塊中聲明ResponseBody,以便它自動關閉。

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

對於某些人來說,直接關閉「Response」而不是「ResponseBody」可能會稍微好一些。也就是說,關閉響應關閉了底層ResponseBody ...對於我的用例關閉響應效果稍好一點。 –

+0

我無法使用try-with-resources方法,因爲我的方法需要返回'Response'實例,如果成功(請參閱我自己的答案),可以用另一種方法讀取它。 – Alphaaa