java httpclient释放_HttpClient的释放问题

最近遇到了这样一个问题,在Android开启StrictMode的时候,会抛出一个异常如下:

04-01 16:07:56.864: E/StrictMode(26867): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.

04-01 16:07:56.864: E/StrictMode(26867): java.lang.Throwable: Explicit termination method 'close' not called

04-01 16:07:56.864: E/StrictMode(26867):         at dalvik.system.CloseGuard.open(CloseGuard.java:184)

04-01 16:07:56.864: E/StrictMode(26867):         at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:271)

04-01 16:07:56.864: E/StrictMode(26867):         at com.android.org.conscrypt.OpenSSLSocketImpl.waitForHandshake(OpenSSLSocketImpl.java:598)

04-01 16:07:56.864: E/StrictMode(26867):         at com.android.org.conscrypt.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:560)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.io.SocketInputBuffer.(SocketInputBuffer.java:70)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:172)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)

04-01 16:07:56.864: E/StrictMode(26867):         at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)

异常大概是说资源没有释放,需要显示的调用close方法。从log上看是网络访问时出现的问题(我使用的是HttpClient)。

但是在关闭StrictMode的时候程序可以完全正常的运行。原因何在呢?

通过查看HttpClient官方文档发现,在HttpClient请求结束后需要销毁HttpEntity,这样才可以使网络连接返回连接池等待下一次重用(如果不需要重用的话也可以直接关掉连接)。

官方推荐的HttpEntity销毁方法:HttpEntity#consumeContent

在查看代码时发现,HttpEntity并没有销毁。可是其他网络请求部分的HttpEntity也都没有销毁,为什么只有这一个网络请求会报错呢?而且代码中有监听网络超时并关掉连接的处理,为什么还会出现这个问题呢?

仔细查看发现,出现问题的部分与其他部分稍有不同。出现问题的网络请求在解析响应的时候,并不需要解析Entity,他的响应结果是放在Headers里面的。也就是说这部分代码在请求结束的时候没有调用HttpResponse#getEntity#getContent方法。

查看HttpClient文档发现getContent方法也可以使Entity销毁。

所以就是这个原因使StrictMode抛出资源未释放的异常。

因为有了网络超时监听的处理,所以在关闭StrictMode的时候并不会出现什么问题,因为没有释放的连接会等到网络超时的时候会被释放。

在使用HttpClient时一定要注意资源的释放。即使有网络超时自动关闭连接的监听,StrictMode也会报告没有释放资源的异常,因为连接不会立即释放,需要等待超时时间的到来才会release,这样影响了程序的性能。

附HttpClient源码分析:

1.BasicHttpEntity#getContent源码:

91f074dd8d272a2296a0d4fb05c99800.png

在getContent方法中将contentObtained置为true;标记content已经被获取过了,在其他地方检测这个标记,如果资源被获取过,那么就会release掉这个连接。

2.BasicHttpEntity#consumeContent源码:

8d0d07fea39beced875c2073951984e0.png

关闭content(content类型为InputStream)

3.EntityUtils#toString

05f315e529342f432d14eb68a30289e6.png

在EntityUtils#toString方法的最后直接进行了reader.close();因此直接调用EntityUtils#toString方法后相当于调用了HttpEntity#consumeContent方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值