CloseableHttpResponse用完需要手动关闭吗

不用。

前提是调用了EntityUtils去读取过了。

当我们使用调用CloseableHttpClient的时候,调用CloseableHttpClient.execute(httpPost)方法会返回CloseableHttpResponse对象,CloseableHttpResponse的唯一实现类是HttpResponseProxy,我们来研究下不手动close,这个对象能否被正常回收,是否有资源被占用等bad situations

分析下HttpResponseProxy源码,发现这个类只有两个成员变量,分别是HttpResponse和ConnectionHolder:只要这俩被回收,就是jvm安全的。

CloseableHttpResponse用完需要手动关闭吗_第1张图片

HttpResponse在这里是BasicHttpResponse,这个对象里有一个HttpEntity的成员变量,HttpEntity里有一个输入流

只要这个流被回收了就是安全的。

然后再来看看ConnectionHolder里有什么

CloseableHttpResponse用完需要手动关闭吗_第2张图片

额,manager和managedConn这是什么?先不管,看下方法栈

CloseableHttpResponse用完需要手动关闭吗_第3张图片

只要manager和managedConn被回收了就是安全的。

 

好,我们回去看HttpResponseProxy,注意看HttpResponseProxy的构造函数,response这个对象被增强了,response.getEntity得到的对象将变ResponseEntityProxy,注意这个类实现了EofSensorWatcher

// 构造函数
public HttpResponseProxy(final HttpResponse original, final ConnectionHolder connHolder) {
        this.original = original;
        this.connHolder = connHolder;
        ResponseEntityProxy.enchance(original, connHolder);
    }


// 增强代码
class ResponseEntityProxy extends HttpEntityWrapper implements EofSensorWatcher {

    private final ConnectionHolder connHolder;

    public static void enchance(final HttpResponse response, final ConnectionHolder connHolder) {
        final HttpEntity entity = response.getEntity();
        if (entity != null && entity.isStreaming() && connHolder != null) {
            response.setEntity(new ResponseEntityProxy(entity, connHolder));
        }
    }

当我们调用EntityUtils.toString方法去消费entity对象,这个方法会调用entity的getContent方法去获取输入流。

CloseableHttpResponse用完需要手动关闭吗_第4张图片

而这个entity就是增强后的这个ResponseEntityProxy,这个对象的getContent方法返回了EofSensorInputStream。(第二个参数this表示把这个inputStream的EofSensorWatcher设置为ResponseEntityProxy对象)

    @Override
    public InputStream getContent() throws IOException {
        return new EofSensorInputStream(this.wrappedEntity.getContent(), this);
    }

 

EofSensorInputStream.java

    @Override
    public int read(final byte[] b, final int off, final int len) throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            try {
                l = wrappedStream.read(b,  off,  len);
                checkEOF(l);
            } catch (final IOException ex) {
                checkAbort();
                throw ex;
            }
        }

        return l;
    }


protected void checkEOF(final int eof) throws IOException {

        final InputStream toCheckStream = wrappedStream;
        if ((toCheckStream != null) && (eof < 0)) {
            try {
                boolean scws = true; // should close wrapped stream?
                if (eofWatcher != null) {
                    scws = eofWatcher.eofDetected(toCheckStream);
                }
                if (scws) {
                    toCheckStream.close();
                }
            } finally {
                wrappedStream = null;
            }
        }
    }

 

ResponseEntityProxy实现EofSensorWatcher接口,这个就是HttpResponse里的entity对象,releaseConnection用于清除这个代理对象的connHolder对象,也就是HttpResponseProxy的ConnectionHolder对象。

CloseableHttpResponse用完需要手动关闭吗_第5张图片

    @Override
    public boolean eofDetected(final InputStream wrapped) throws IOException {
        try {
            // there may be some cleanup required, such as
            // reading trailers after the response body:
            if (wrapped != null) {
                wrapped.close();
            }
            releaseConnection();
        } catch (final IOException ex) {
            abortConnection();
            throw ex;
        } catch (final RuntimeException ex) {
            abortConnection();
            throw ex;
        } finally {
            cleanup();
        }
        return false;
    }

 

httpcomponent4.5以上版本,默认使用 EofSensorInputStream 作为输入流,这个流对象在每次读取之后都会检查是否已经读取到末尾,如果读取完,则关闭ChunkedInputStream并释放连接 releaseConnection(),就算没有关闭,如果是通过apache的EntityUtils的toString方法获取HttpEntity对象里的内容,也会在return之前执行finally里的close方法

releaseConnection这个方法释放了最开始我们提到的ConnectionHolder,而close方法则关闭了HttpResponse里的流,因此最后是安全的,即使没有手动调用close方法,全部得益于EofSensorInputStream这个输入流。

老眼昏花,写的比较乱。太难了。。。。。

你可能感兴趣的:(java)