10

After reading all sort of docs on Java HttpURLConnection, I'm still quite confused as what kind of pooling it does and how it hands connections.

For example, the following code

URL url = new URL(someUrl);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
OutputStream os = connection.getOutputStream();
InputStream is = connection.getInputStream();

/** Write something to os and flush */
/** Read from is */

os.close();
is.close();
connection.disconnect();
  1. Do both os and is need to be flushed and closed for the underlying socket to be reusable?

  2. Will connection.disconnect() close the underlying socket (and hence make it unreusable)? Does keep-alive affect this behavior?

  3. If I use different URL objects, but with the same URL, will the connections created from them share the underlying sockets? How about when the host part of the URL is the same, but paths are different?

  4. When will pooled connections be destroyed?

  5. What's the system property that controls the size of the pool?

Additionally, if you could also compare the Android version with Java it would be great.

Thanks

user207421
  • 305,947
  • 44
  • 307
  • 483
stackoverflower
  • 3,885
  • 10
  • 47
  • 71

2 Answers2

13
  1. Do both os and is need to be flushed and closed for the underlying socket to be reusable?

Closing the input stream is sufficient. You can't flush an input stream, and flushing an output stream before close is redundant.

  1. Will connection.disconnect() close the underlying socket (and hence make it unreusable)?

It 'acts as a hint' to close the underlying connection.

Does keep-alive affect this behavior?

Yes. If it isn't present, the connection must be closed.

  1. If I use different URL objects, but with the same URL, will the connections created from them share the underlying sockets?

Yes.

How about when the host part of the URL is the same, but paths are different?

Yes.

  1. When will pooled connections be destroyed?

After an idle timeout.

  1. What's the system property that controls the size of the pool?

I'm not aware that there is one, but if there is it will be defined in the Networking Properties page which you can find via the Javadoc.

Additionally, if you could also compare the Android version with Java it would be great.

I believe that Android doesn't do pooling at all, but this should change when they switch to the OpenJDK source.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Regarding the first point I did two tests with 10 requests each. In the first test I got the InputStream using getContent and just closed it. In the second test I also read the entire stream before closing it. The results were different for the second request in each round: when I just closed the InputStream it was considerably slower then the other 8 requests (first was 800ms, second was 600 and the rest was 140ms), when I also read the response only the first took 800 and the rest took 140ms. Not sure why this is happening. Using JDK 1.8.0_51. – Constantino Cronemberger Nov 28 '16 at 15:11
  • 1
    Looks like the observed behavior is related with http.KeepAlive.remainingData that was introduced in JDK 1.6. http://docs.oracle.com/javase/6/docs/technotes/guides/net/http-keepalive.html – Constantino Cronemberger Nov 28 '16 at 15:42
  • @Constantino Of course if you misuse the connection it can't be pooled. That's not surprising. To reuse one you haven't exhausted the input on, it would have to do hat itself, which might block. – user207421 Jun 09 '17 at 23:06
  • @Angelo It is mostly inferred from the Javadoc, and as I said it does not refer to Android up to the point I mentioned. I've also read the source code. – user207421 Jun 09 '17 at 23:08
  • @EJP I guessed so much, my question was more along: Could you edit some pointers to the specific documentation into your question? – Angelo Fuchs Jun 11 '17 at 17:35
  • @AngeloFuchs Come off it. It isn't the Encyclopaedia Brittannica: just a single Web page. Here is a [link](https://docs.oracle.com/javase/8/docs/api/java/net/HttpURLConnection.html) to the whole thing. – user207421 Mar 26 '18 at 03:44
0

Actually, the accepted answer is not applicable to Android at all:

  1. Both the http.keepAlive and http.maxConnections system properties are ignored by Android because the networking code reads these properties during static initialization (i.e. during process/JVM creation, not checking if they change later). See https://code.google.com/archive/p/android-developer-preview/issues/2578.

  2. This comment is incorrect, as connection pooling is indeed supported in Android (see next item for more details):

    I believe that Android doesn't do pooling at all, but this should change when they switch to the OpenJDK source.

  3. The connection pooling implemented in OkHttp (which is the implementation under Android's HttpUrlConnection class) treats the count as a global limit across all servers (default is 5). This is actually a bug and doesn't match the standard Java implementation. See https://github.com/square/okhttp/issues/1843.

I encountered this trying to disable connection pooling and found that neither had any effect (confirmed with Android O as well). Instead, Android/OkHttp would consistently reuse 5 connections left over from previous http requests.

LBC
  • 411
  • 3
  • 9
  • Reading system properties during system intialization isn't the same thing as ignoring them. – user207421 Apr 03 '20 at 09:23
  • @user207421 - It is the same when you can only change a system property from your app code, which occurs *after* it's already applied and changing it later has no effect. If you have some way to get around that, then provide it. Otherwise, your comment is not useful and misleading folks into thinking they can change these system properties and have it take effect. – LBC Apr 05 '20 at 21:20
  • But claiming that they are ' ignored by Android because the networking code reads these properties during static initialization' is false. They *aren't* 'ignored' at all, they are read during static initialization, and the Sun/Oracle JVMs behave the same way with nearly all system properties, so it isn't even Android-specific. You're contradicting yourself. – user207421 Aug 12 '21 at 10:20
  • Painful trying to explain this to user207421. Last try: if these http system properties are only ever set via static initialization, then how would any Android app be able to change it? For non-rooted Android, you can't. IOW, the networking code ignores _changes_ to these properties made by an Android app since an app can only change the properties _after_ the fact. This is the difference b/t a JVM running an OS where you can control the system properties it is launched with (PC) versus one where you cannot (Android). – LBC Aug 17 '21 at 23:35