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源码:

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

2.BasicHttpEntity#consumeContent源码:

关闭content(content类型为InputStream)

3.EntityUtils#toString

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

时间: 2024-10-21 22:52:58

HttpClient的释放问题的相关文章

JAVA 抓取网页之GET方法

HTTP请求方式有GET,POST两种.这里使用GET方式,请求"https://www.baidu.com". 引进 appache 的httpclient包,下载地址http://hc.apache.org/httpcomponents-client-4.5.x/download.html 先贴代码 package Test; import java.io.IOException; import org.apache.http.HttpEntity; import org.apac

微软认知服务应用秘籍 – 搭建基于云端的中间层以支持跨平台的智能视觉服务

不断演进的应用场景 初级应用场景—宅在家里 场景:Bob同学有一天在网上看到了一张建筑物的图片,大发感慨:"好漂亮啊!这是哪里?我要去亲眼看看!"Bob同学不想问别人,可笑的自尊心让他觉得这肯定是个著名的建筑,如果自己不知道多丢脸!怎么解决Bob同学的烦恼呢? 我们看看微软认知服务是否能帮助到Bob同学,打开这个链接: https://azure.microsoft.com/zh-cn/services/cognitive-services/computer-vision/ 向下卷滚屏

HttpClient 释放连接

Release the Connection:释放连接 This is a crucial step to keep things flowing. We must tell HttpClient that we are done with the connection and that it can now be reused. Without doing this HttpClient will wait indefinitely for a connection to free up so

HttpClient使用详解 (一)

Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们再讨论),它不仅是客户端发送Http请求变得容易,而且也方便了开发人员测试接口(基于Http协议的),即提高了开发的效率,也方便提高代码的健壮性.因此熟练掌握HttpClient是很重要的必修内容,掌握HttpClient后,相信对于Http协议的了解会更加深入. 一.简介 HttpClient是Apache Jakarta Common下的子项目,用

HttpClient的CircularRedirectException异常原因及解决办法

HttpClient的CircularRedirectException异常原因及解决办法 这两天在使用我自己爬虫抓取网页的时候总是出现 org.apache.http.client.ClientProtocolException at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:909) at org.apache.http.impl.client.AbstractHttpClie

接口测试(二)—HttpClient

使用HttpClient进行接口测试,所需要使用的相关代码 HttpClient进行接口测试所需jar包:httpclient.jar.httpcore.jar.commons-logging.jarGet请求://创建httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();//如果发送的是GET请求,创建HttpGet对象HttpGet httpget = new HttpGet("http://www.

java Webservice(一)HttpClient使用(二)

HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源.虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活.HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的.最新的.功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议

Android网络编程 HttpClient Socket

 目前Android平台有3中网络通信接口: 1.java.net.*(标准的java接口):URLConnection/HttpURLConnection类. 2.org.apache(Apache接口):HttpClient接口 3.Android.net(Android网络接口):通过对Apache的HttpClient接口的封装来实现的一个Http编程接口. 一.标准的java接口: 通过Http请求一般有两种方式:get与post get方式:get请求可以获取静态页面,也可以把参

HttpClient 4.3.6教程 第1章 基础 【翻译】

第1章基础 1.1请求执行 HttpClient大部分的基础函数都是在执行HTTP的方法.一个HTTP方法执行包括一个或多个HTTP请求/HTTP应答交换,通常这已经在HttpClient内部操作了. 用户提供一个请求对象,HttpClient将这个请求传输给目标服务器,服务器返回一个相应的应答结构,如果不成功则抛出一个异常. 很自然地,了解HttpClientAPI的切入点是上面阐述里规定的HttpClient接口. 这是一个最简单请求执行例子: CloseableHttpClienthttp