About HttpURLConnection

public byte[] getUrlBytes(String urlSpec) throws IOException {
URL url = new URL(urlSpec);
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
InputStream in = connection.getInputStream();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException(connection.getResponseMessage() + ": with " + urlSpec);
}
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = in.read(buffer)) > 0)
{
out.write(buffer, 0, bytesRead);
}
out.close();
return out.toByteArray();
} finally {
connection.disconnect();
}
}

I have several questions.

  1. out.close()
    This code calls out.close() and dosen’t call in.close().
    Is it OK??
    Or does connection.disconnect() perform in.close() internally?

  2. connection.disconnect()
    I’m confused about the behavior of disconnect().

    https://docs.oracle.com/javase/9/docs/api/java/net/HttpURLConnection.html
    Calling the close() methods on the InputStream or OutputStream of an HttpURLConnection after a request may free network resources associated with this instance but has no effect on any shared persistent connection. Calling the disconnect() method may close the underlying socket if a persistent connection is otherwise idle at that time.
    —> java doc says that calling disconnect() may close TCP connection.

    https://developer.android.com/reference/java/net/HttpURLConnection.html
    Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.
    —> android doc recommends to always call disconnect().

    To reduce latency, this class may reuse the same underlying Socket for multiple request/response pairs. As a result, HTTP connections may be held open longer than necessary. Calls to disconnect() may return the socket to a pool of connected sockets.
    —> android doc says that the connection keeps alive and the socket can be reused after disconnect(), right?

    void disconnect ()
    Indicates that other requests to the server are unlikely in the near future. Calling disconnect() should not imply that this HttpURLConnection instance can be reused for other requests.
    —> android doc says that the connection can’t be reused after disconnect(), right??

    ==> In android, does disconnect() close TCP connection?
    Does android recommend to disable persistent connection?

  3. handling IOException of getInputStream()
    Java Training recommends to use getErrorStream() to reuse TCP connection.
    In android, calling getErrorStream() is unnecessary??

    http://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html
    When the application finishes reading the response body or when the application calls close() on the InputStream returned by URLConnection.getInputStream(), the JDK’s HTTP protocol handler will try to clean up the connection and if successful, put the connection into a connection cache for reuse by future HTTP requests.

    Do not abandon a connection by ignoring the response body. Doing so may results in idle TCP connections. That needs to be garbage collected when they are no longer referenced.
    If getInputStream() successfully returns, read the entire response body.
    When calling getInputStream() from HttpURLConnection, if an IOException occurs, catch the exception and call getErrorStream() to get the response body (if there is any).
    Reading the response body cleans up the connection even if you are not interested in the response content itself. But if the response body is long and you are not interested in the rest of it after seeing the beginning, you can close the InputStream. But you need to be aware that more data could be on its way. Thus the connection may not be cleared for reuse.
    Here’s a code example that complies to the above recommendation:
    try {
    URL a = new URL(args[0]);
    URLConnection urlc = a.openConnection();
    is = conn.getInputStream();
    int ret = 0;
    while ((ret = is.read(buf)) > 0) {
    processBuf(buf);
    }
    // close the inputstream
    is.close();
    } catch (IOException e) {
    try {
    respCode = ((HttpURLConnection)conn).getResponseCode();
    es = ((HttpURLConnection)conn).getErrorStream();
    int ret = 0;
    // read the response body
    while ((ret = es.read(buf)) > 0) {
    processBuf(buf);
    }
    // close the errorstream
    es.close();
    } catch(IOException ex) {
    // deal with the exception
    }
    }

Hi jeje

Class “sun.net.www.protocol.http.HttpURLConnection” is the subclass of “java.net.HttpURLConnection”.

The implementation of the method disconnect() can answer your questions.

line 2548

http://www.docjar.com/html/api/sun/net/www/protocol/http/HttpURLConnection.java.html

 2507       public void disconnect() {
 2508   
 2509           responseCode = -1;
 2510           if (pi != null) {
 2511               pi.finishTracking();
 2512               pi = null;
 2513           }
 2514   
 2515           if (http != null) {
                        // ......
 2540   
 2541               if (inputStream != null) {
 2542                   HttpClient hc = http;
 2543   
 2544                   // un-synchronized
 2545                   boolean ka = hc.isKeepingAlive();
 2546   
 2547                   try {
 2548                       inputStream.close();
 2549                   } catch (IOException ioe) { }
 2550   
 2551                   // if the connection is persistent it may have been closed
 2552                   // or returned to the keep-alive cache. If it's been returned
 2553                   // to the keep-alive cache then we would like to close it
 2554                   // but it may have been allocated
 2555   
 2556                   if (ka) {
 2557                       hc.closeIdleConnection();
 2558                   }
 2559   
 2560   
 2561               } else {
 2562                   // We are deliberatly being disconnected so HttpClient
 2563                   // should not try to resend the request no matter what stage
 2564                   // of the connection we are in.
 2565                   http.setDoNotRetry(true);
 2566   
 2567                   http.closeServer();
 2568               }
 2569   
 2570               //      poster = null;
 2571               http = null;
 2572               connected = false;
 2573           }
 2574           cachedInputStream = null;
 2575           if (cachedHeaders != null) {
 2576               cachedHeaders.reset();
 2577           }
 2578       }