相关文章推荐
坚强的碗  ·  腾讯AI ...·  4 月前    · 
年轻有为的针织衫  ·  mysql ...·  4 月前    · 
逆袭的围巾  ·  Database - IBM Db2·  9 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am using OkHttp 3, and I keep getting leaked connection warnings:

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

Everytime I get a ResponseBody, I either call .string() which supposedly closes the stream for me, or I explicitly close it in a finally block, in the following way:

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

My application makes intense use of the network, and yet that warning appears frequently. I never observed any problem caused by this presumed leak, but I would still like to understand if and what I am doing wrong.

Could anyone shed some light on this?

By upgrading to OkHttp 3.7, Eclipse started warning me of potential resource leaks. I found my problem to be in this method I wrote:

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);
            throw new IOException(String.format("Cannot get successful response for url %s", url));
    return response;

I assumed that by always calling getResponse(url, client).body().string() the stream would close automatically. But, whenever a response was unsuccessful, an exception would raise before the execution of .string(), thus the stream would remain open.

Adding an explicit close in case of unsuccessful response solved the problem.

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

As mentioned in the other answers, you have to close the response. A slightly cleaner approach would be to declare the ResponseBody in the try block, so that it will be automatically closed.

try(ResponseBody body = ....){
                For some it might be slightly nicer to close the Response rather than the ResponseBody directly.  That is, closing Response closes the underlying ResponseBody ... for my use cases closing Response works a little bit better.
– Rob Bygrave
                Jan 9, 2017 at 0:45
                I could not use a try-with-resources approach, because my method needed to return the Response instance, to be read by another method if successful (see my own answer).
– Alphaaa
                May 5, 2017 at 15:08
                if you use Kotlin and the new okhttpclient v4, simply consume the response using a client.newCall(..).execute().use {response -> ... }
– Jilles van Gurp
                Jul 30, 2019 at 15:21
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.