zoukankan      html  css  js  c++  java
  • 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方法
  • 相关阅读:
    redis 笔记
    经验
    增加模块-概念图
    node API buffer
    VS2010中使用CL快速 生成DLL的方法
    WIN7下VS2010中使用cl编译的步骤
    Win7下VS2010编译的程序在XP报错:找不到msvcp100d.dll或者msvcp100.dll
    C#速学
    Windows下架设SVN服务
    Redis 压力测试
  • 原文地址:https://www.cnblogs.com/younghome/p/4609022.html
Copyright © 2011-2022 走看看