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?
Network failures can be due to client connectivity problems, server availability problems, or anything between. OkHttp supports connect, read, and write timeouts. In this example, we built our client with a readTimeout of 1 seconds, while the URL is served with 2 seconds of delay:
2. OkHttp Overview OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features such as connection pooling (if HTTP/2 isn’t available), transparent GZIP compression, and response caching to avoid the network completely for repeated requests.
Asynchronous GET With OkHttp Now, to make an asynchronous GET we need to enqueue a Call. A Callback allows us to read the response when it is readable. This happens after the response headers are ready. Reading the response body may still block. OkHttp doesn't currently offer any asynchronous APIs to receive a response body in parts: 6.
OkHttp Overview. OkHttp is an efficient HTTP & HTTP/2 client for Android and Java applications. It comes with advanced features such as connection pooling (if HTTP/2 isn’t available), transparent GZIP compression, and response caching to avoid the network completely for repeated requests.
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); else 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 = ....){ .... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With