olingClientConnectionManager泄漏内存

olingClientConnectionManager泄漏内存

本文介绍了使用Java的Apache PoolingClientConnectionManager泄漏内存,如何解决呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在晚上我的Web应用程序运行的工作!而满足的问题!它采用了大量的记忆!结果
我用命令来查找哪些功能占据了Java资源!结果
这是结果是:

  [tomcat的@ uhzd006525〜] $ jstack 2365 | grep的93F -A 30
             - 停车等待< 0x00000007eac93f68> (一java.util.concurrent.locks.AbstractQueuedSynchronizer中的$的ConditionObject)
            在java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            在java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            在org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:131)
            在org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:281)
            在org.apache.http.pool.AbstractConnPool.access $ 000(AbstractConnPool.java:62)
            在org.apache.http.pool.AbstractConnPool $ 2.getPoolEntry(AbstractConnPool.java:176)
            在org.apache.http.pool.AbstractConnPool $ 2.getPoolEntry(AbstractConnPool.java:172)
            在org.apache.http.pool.PoolEntryFuture.get(PoolEntryFuture.java:100)
            在org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection(PoolingClientConnectionManager.java:212)
            在org.apache.http.impl.conn.PoolingClientConnectionManager$1.getConnection(PoolingClientConnectionManager.java:199)
            在org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:456)
            在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
            在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
            在com.trendata.spider.PageGetter.getPageContent(PageGetter.java:262)
            在com.trendata.spider.PageGetter.getTaobaoContent(PageGetter.java:376)
            在com.trendata.taobao.MbpBkDataCreator.getBkMbpValue(MbpBkDataCreator.java:48)
            在com.trendata.taobao.MbpBkDataCreator.getIntoStores(MbpBkDataCreator.java:106)
            在com.trendata.service.impl.OddJobsServiceImpl.getLast7DaysIntoStore(OddJobsServiceImpl.java:448)
            在sun.reflect.GeneratedMethodAccessor205.invoke(来源不明)
            在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            在java.lang.reflect.Method.invoke(Method.java:601)
            在org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
            在org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
            在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
            在com.trendata.service.interceptor.MethodCacheInterceptor.invoke(MethodCacheInterceptor.java:32)
            在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
            在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
            在$ Proxy144.getLast7DaysIntoStore(来源不明)
            在sun.reflect.GeneratedMethodAccessor205.invoke(来源不明)
            在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
     -
    GC任务线程#0(ParallelGC)PRIO = 10 = TID NID 0x0000000000d46000 = 0x93f可运行    GC任务线程#1(ParallelGC)PRIO = 10 = TID NID 0x0000000000d48000 = 0x940可运行    VM周期性任务线程PRIO = 10 = TID NID 0x00002aaabc059800 = 0x94b等待条件    JNI全局引用:342
    线程114PRIO = 10 = TID NID 0x000000002281e800 = 0xf4a等待条件[0x000000004c7d3000]
       java.lang.Thread.State中:等待(停车场)
            在sun.misc.Unsafe.park(本机方法)
             - 停车等待< 0x0000000790f5dc40> (一java.util.concurrent.locks.AbstractQueuedSynchronizer中的$的ConditionObject)
            在java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            在java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            在java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
            在java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
            在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
            在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:603)
            在java.lang.Thread.run(Thread.java:722)    线程113PRIO = 10 = TID NID 0x0000000022624800 = 0xf48等待条件[0x000000004c6d2000]
       java.lang.Thread.State中:等待(停车场)
            在sun.misc.Unsafe.park(本机方法)
             - 停车等待< 0x0000000790f5dc40> (一java.util.concurrent.locks.AbstractQueuedSynchronizer中的$的ConditionObject)
            在java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            在java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            在java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
            在java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
            在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
            在java.util.concurrent.ThreadPoolExecutor中的$ Worker.run(ThreadPoolExecutor.java:603)
            在java.lang.Thread.run(Thread.java:722)    线程112PRIO = 10 = TID NID 0x00000000225d9800 = 0xf37等待条件[0x000000004c5d1000]
       java.lang.Thread.State中:等待(停车场)
            在sun.misc.Unsafe.park(本机方法)
             - 停车等待< 0x0000000790f5dc40> (一java.util.concurrent.locks.AbstractQueuedSynchronizer中的$的ConditionObject)
            在java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            在java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            在java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
     -
    GC任务线程#0(ParallelGC)PRIO = 10 = TID NID 0x000000001f287000 = 0x7d30可运行    GC任务线程#1(ParallelGC)PRIO = 10 = TID NID 0x000000001f288800 = 0x7d31可运行    VM周期性任务线程PRIO = 10 = TID NID 0x000000001f3d1000 = 0x7d39等待条件    JNI全局引用:579

这是code所发生的问题:

 公共类PageGetter {
    私有静态最后登录日志= LogFactory.getLog(serviceLogger);
    私有静态SyncBasicHttpParams的HttpParams = NULL;
    私人的HttpClient HttpClient的= NULL;
    私有静态PoolingClientConnectionManager的ConnectionManager = NULL;
    私有静态整数errorSleepTime =新的整数(PropertyGetter.getInstance()的getProperty(errorpagesleeptime)。);    公共字符串getFinalRedirectURL(字符串URL)抛出ClientProtocolException,IOException异常{
        如果(URL == NULL){
            返回null;
        }
        如果(url.trim()startsWith(HTTP://!)){
            URL =HTTP://+网址;
        }
        HttpContext的localContext =新BasicHttpContext();
        HTTPGET HTTPGET =新HTTPGET(URL);
        如果(的ConnectionManager == NULL ||的HttpParams == NULL || this.httpClient == NULL){
            this.initHttpManager();
        }
        this.httpClient.execute(HTTPGET,localContext);
        HttpHost目标=(HttpHost)localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
        串finalURL = target.toString();
        httpget.abort();
        返回finalURL;
    }    私人无效initHttpManager(){
        //创建并初始化HTTP参数
        如果(的HttpParams == NULL){
            的HttpParams =新SyncBasicHttpParams();
            httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT,60000);
            httpParams.setParameter(HTTP.CONTENT_ENCODING,GBK);
            HttpProtocolParams.setVersion(的HttpParams,HttpVersion.HTTP_1_1);
        }
        如果(的ConnectionManager == NULL){
            SchemeRegistry schemeRegistry =新SchemeRegistry();
            schemeRegistry.register(新计划(HTTP,80,PlainSocketFactory.getSocketFactory()));
            尝试{
                //安全套接字
                CTX的SSLContext = SSLContext.getInstance(TLS);
                X509TrustManager TM =新X509TrustManager(){
                    @覆盖
                    公共x509证书[] getAcceptedIssuers()为{
                        返回null;
                    }                    @覆盖
                    公共无效checkClientTrusted(x509证书[]为arg0,ARG1字符串)抛出CertificateException {
                    }                    @覆盖
                    公共无效checkServerTrusted(x509证书[]为arg0,ARG1字符串)抛出CertificateException {
                    }
                };
                ctx.init(空,新的TrustManager [] {} TM,NULL);
                SSLSocketFactory的SSF =新的SSLSocketFactory(CTX,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                schemeRegistry.register(新计划(https开头,443,SSF));
            }赶上(例外五){
                log.error(无法创建连接管理器+ E);
            }
            的ConnectionManager =新PoolingClientConnectionManager(schemeRegistry);
        }
        this.httpClient =新DefaultHttpClient(的ConnectionManager,的HttpParams);
        this.httpClient.getParams()的setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS,真)。
        HttpClientParams.setCookiePolicy(this.httpClient.getParams(),CookiePolicy.BROWSER_COMPATIBILITY);
    }    公共字符串getPostPageContent(字符串URL,列表和LT;&的NameValuePair GT;标题,列表与LT;&的NameValuePair GT; PARAMS){
        字符串strPage = NULL;
        如果(URL == NULL){
            返回null;
        }
        如果(!url.trim()。startsWith(HTTP)){
            URL =HTTP://+网址;
        }
        HttpPost httpPost =新HttpPost(URL);
        HttpEntity实体= NULL;
        尝试{
            如果(PARAMS!= NULL){
                httpPost.setEntity(新UrlEn codedFormEntity(参数,可以UTF-8));
            }
            如果(头!= NULL){
                迭代器<&的NameValuePair GT; itrHeaders = headers.iterator();
                而(itrHeaders.hasNext()){
                    的NameValuePair头= itrHeaders.next();
                    httpPost.setHeader(header.getName(),header.getValue());
                }
            }
            HttpContext的localContext =新BasicHttpContext();
            如果(的ConnectionManager == NULL ||的HttpParams == NULL || this.httpClient == NULL){
                this.initHttpManager();
            }
            HTT presponse响应= this.httpClient.execute(httpPost,localContext);
            //得到响应体作为一个字节数组
            实体= response.getEntity();
            如果(实体!= NULL){
                strPage = EntityUtils.toString(实体);
            }
        }赶上(例外五){
            的ConnectionManager = NULL;
            的HttpParams = NULL;
            this.httpClient = NULL;
            this.errorHandler(URL,E);
        } {最后
            httpPost.abort();            如果(实体!= NULL){
                尝试{
                    EntityUtils.consume(实体);
                }赶上(例外E2){
                    e2.printStackTrace();
                    log.error(错误时消耗实体,E2);
                }
            }
        }
        如果(strPage!= NULL){
            模式模式= Pattern.compile(\\\\ S);
            匹配匹配= pattern.matcher(strPage);
            strPage = matcher.replaceAll();
            strPage = strPage.replaceAll(////,);
        }
        返回strPage;
    }    私人字符串的getURL(字符串URL,列表和LT;&的NameValuePair GT;头){
        如果(头== NULL){
            返回URL;
        }
        地图<字符串,字符串>地图=新的HashMap<字符串,字符串>();
        如果(url.contains(?)){
            字符串str = url.substring(url.indexOf()+ 1?);
            URL = url.substring(0,url.indexOf()?);
            的String [] =可疑交易报告str.split(与&);
            的for(int i = 0;可疑交易报告= NULL&放大器;!&安培; I< strs.length;我++){
                如果序列(STR [I]。载(=)){
                    字符串键=可疑交易报告[I] .substring(0,可疑交易报告[I] .indexOf(=));
                    字符串值=可疑交易报告[I] .substring序列(STR [I] .indexOf(=)+ 1);
                    map.put(键,值);
                }
            }
        }
        迭代器<&的NameValuePair GT; itrHeaders = headers.iterator();
        而(itrHeaders.hasNext()){
            的NameValuePair头= itrHeaders.next();
            如果(头= NULL&放大器;!&安培;!header.getName()= NULL和放大器;&安培; header.getValue()!= NULL){
                尝试{
                    map.put(URLEn coder.en code(header.getName(),UTF-8),URLEn coder.en code(header.getValue(),UTF- 8));
                }赶上(例外五){
                    log.error(无法解析参数+ E);
                }
            }
        }
        如果(map.keySet()== NULL){
            返回URL;
        }
        迭代器<串GT; ITR = map.keySet()迭代器()。
        字符串参数=;
        而(itr.hasNext()){
            字符串键= itr.next();
            如果(键= NULL&放大器;!&安培; key.length()0){
                参数=参数+键+=+ map.get(键)+&放大器;;
            }
        }
        如果(parameters.length()大于0){
            URL = URL +? +参数;
        }
        返回URL;
    }    私人无效的ErrorHandler(字符串URL,异常五){
        尝试{
            视频下载(errorSleepTime);
            log.error(无法打开链接+ URL +休眠+ errorSleepTime + E);
        }赶上(例外E1){
            log.error(错误沉睡+ errorSleepTime + E1);
        }
    }    / **
     *获取页面的URL字符串
     *
     * @参数网址
     * @返回
     * /
    公共字符串getPageContent(字符串URL,列表和LT;&的NameValuePair GT;头){
        URL = StringFilter.replaceUni code(URL);
        字符串strPage = NULL;
        如果(URL == NULL){
            返回null;
        }
        如果(!url.trim()。startsWith(HTTP)){
            URL =HTTP://+网址;
        }
        如果(url.endsWith(/)){
            网址= url.substring(0,url.lastIndexOf(/));
        }
        HTTPGET HTTPGET = NULL;
        HttpEntity实体= NULL;
        尝试{
            如果(的ConnectionManager == NULL ||的HttpParams == NULL || this.httpClient == NULL){
                this.initHttpManager();
            }
            URL = this.getURL(URL,标题);
            = HTTPGET HTTPGET新(URL);
            HttpContext的localContext =新BasicHttpContext();
            HTT presponse响应= this.httpClient.execute(HTTPGET,localContext);
            实体= response.getEntity();
            如果(实体!= NULL){
                字符串charset = ContentType.getOrDefault(实体).getCharset()的toString()。
                如果(字符集== NULL){
                    字符集=UTF-8;
                }
                strPage = EntityUtils.toString(实体,CHARSET);
                strPage = strPage.replaceAll(\\ r,);
                strPage = strPage.replaceAll(\\ n,);
                //空格
                strPage = strPage.replaceAll(与& NBSP;,);
            }
        }赶上(例外五){
            的ConnectionManager = NULL;
            的HttpParams = NULL;
            this.httpClient = NULL;
            this.errorHandler(URL,E);
        } {最后
            尝试{
                httpGet.abort();
            }赶上(例外五){
                log.error(错误时HttpClient的中止+ E);
            }            如果(实体!= NULL){
                尝试{
                    EntityUtils.consume(实体);
                }赶上(例外E2){
                    e2.printStackTrace();
                    log.error(错误时消耗实体,E2);
                }
            }
        }
        返回strPage;
    }    公共字符串getPageContentSms(字符串URL,列表和LT;&的NameValuePair GT;头){
        URL = StringFilter.replaceUni code(URL);
        字符串strPage = NULL;
        如果(URL == NULL){
            返回null;
        }
        如果(!url.trim()。startsWith(HTTP)){
            URL =HTTP://+网址;
        }
        如果(url.endsWith(/)){
            网址= url.substring(0,url.lastIndexOf(/));
        }
        HTTPGET HTTPGET = NULL;
        HttpEntity实体= NULL;
        尝试{
            如果(的ConnectionManager == NULL ||的HttpParams == NULL || this.httpClient == NULL){
                this.initHttpManager();
            }
            = HTTPGET HTTPGET新(URL);
            HttpContext的localContext =新BasicHttpContext();
            HTT presponse响应= this.httpClient.execute(HTTPGET,localContext);
            实体= response.getEntity();
            如果(实体!= NULL){
                字符串charset = ContentType.getOrDefault(实体).getCharset()的toString()。
                如果(字符集== NULL){
                    字符集=UTF-8;
                }
                strPage = EntityUtils.toString(实体,CHARSET);
                strPage = strPage.replaceAll(\\ r,);
                strPage = strPage.replaceAll(\\ n,);
                strPage = strPage.replaceAll(与& NBSP;,);
            }
        }赶上(例外五){
            的ConnectionManager = NULL;
            的HttpParams = NULL;
            this.httpClient = NULL;
            this.errorHandler(URL,E);
        } {最后
            尝试{
                httpGet.abort();
            }赶上(例外五){
                log.error(错误时HttpClient的中止+ E);
            }            如果(实体!= NULL){
                尝试{
                    EntityUtils.consume(实体);
                }赶上(例外E2){
                    e2.printStackTrace();
                    log.error(错误时消耗实体,E2);
                }
            }
        }
        返回strPage;
    }    公开名单<&的NameValuePair GT; getDefaultHeaders(){
        清单<&的NameValuePair GT;标题=新的ArrayList<&的NameValuePair GT;();
        BasicNameValuePair的NameValuePair =新BasicNameValuePair(接受,
                text / html的,是application / xhtml + xml的,应用/ XML; Q = 0.9 * / *; Q = 0.8);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(接收字符集,GBK,UTF-8,Q = 0.7,*; Q = 0.3);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(接受编码,GBK,UTF-8,Q = 0.7,*; Q = 0.3);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(接受语言,ZH-CN ZH; Q = 0.8);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(缓存控制,最大年龄= 0);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(连接,保持活动);
        headers.add(的NameValuePair);
        的NameValuePair =新BasicNameValuePair(用户代理,
                Mozilla的/ 5.0(Windows NT的6.1; WOW64)为AppleWebKit / 535.19(KHTML,像壁虎)的Chrome / Safari浏览器18.0.1025.162 / 535.19);
        headers.add(的NameValuePair);
        返回头;
    }    公共字符串getTaobaoContent(列表<&的NameValuePair GT; PARAMS){
        返回this.getPageContent(Constant.TAOBAO_API_URL,则params);
    }


解决方案

我们使用与新泽西HttpClient的时候看到了非常类似的问题。线程被封锁等待连接。

在我们的例子中,当我们在GET请求中遇到的错误40X连接池中得到耗尽。

原因是连接从未被释放回池中,除非我们实际读取响应主体(我们在当我们到达客户端错误codeS的情况下没有)。
在源$ C ​​$ C好像你刚才扔ClientProtocolException不读响应..它可能是类似的。

My web application run jobs in night!And meet the problem!It used a lot of memory!
I use the command to find which function occupy the java resource!
It is result:

        [tomcat@uhzd006525 ~]$ jstack 2365 |grep 93f -A 30
            - parking to wait for  <0x00000007eac93f68> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
            at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            at org.apache.http.pool.PoolEntryFuture.await(PoolEntryFuture.java:131)
            at org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:281)
            at org.apache.http.pool.AbstractConnPool.access$000(AbstractConnPool.java:62)
            at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:176)
            at org.apache.http.pool.AbstractConnPool$2.getPoolEntry(AbstractConnPool.java:172)
            at org.apache.http.pool.PoolEntryFuture.get(PoolEntryFuture.java:100)
            at org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection(PoolingClientConnectionManager.java:212)
            at org.apache.http.impl.conn.PoolingClientConnectionManager$1.getConnection(PoolingClientConnectionManager.java:199)
            at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:456)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
            at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
            at com.trendata.spider.PageGetter.getPageContent(PageGetter.java:262)
            at com.trendata.spider.PageGetter.getTaobaoContent(PageGetter.java:376)
            at com.trendata.taobao.MbpBkDataCreator.getBkMbpValue(MbpBkDataCreator.java:48)
            at com.trendata.taobao.MbpBkDataCreator.getIntoStores(MbpBkDataCreator.java:106)
            at com.trendata.service.impl.OddJobsServiceImpl.getLast7DaysIntoStore(OddJobsServiceImpl.java:448)
            at sun.reflect.GeneratedMethodAccessor205.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
            at java.lang.reflect.Method.invoke(Method.java:601)
            at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
            at com.trendata.service.interceptor.MethodCacheInterceptor.invoke(MethodCacheInterceptor.java:32)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
            at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
            at $Proxy144.getLast7DaysIntoStore(Unknown Source)
            at sun.reflect.GeneratedMethodAccessor205.invoke(Unknown Source)
            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    --
    "GC task thread#0 (ParallelGC)" prio=10 tid=0x0000000000d46000 nid=0x93f runnable

    "GC task thread#1 (ParallelGC)" prio=10 tid=0x0000000000d48000 nid=0x940 runnable

    "VM Periodic Task Thread" prio=10 tid=0x00002aaabc059800 nid=0x94b waiting on condition

    JNI global references: 342






    "Thread-114" prio=10 tid=0x000000002281e800 nid=0xf4a waiting on condition [0x000000004c7d3000]
       java.lang.Thread.State: WAITING (parking)
            at sun.misc.Unsafe.park(Native Method)
            - parking to wait for  <0x0000000790f5dc40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
            at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
            at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
            at java.lang.Thread.run(Thread.java:722)

    "Thread-113" prio=10 tid=0x0000000022624800 nid=0xf48 waiting on condition [0x000000004c6d2000]
       java.lang.Thread.State: WAITING (parking)
            at sun.misc.Unsafe.park(Native Method)
            - parking to wait for  <0x0000000790f5dc40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
            at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
            at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1043)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1103)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
            at java.lang.Thread.run(Thread.java:722)

    "Thread-112" prio=10 tid=0x00000000225d9800 nid=0xf37 waiting on condition [0x000000004c5d1000]
       java.lang.Thread.State: WAITING (parking)
            at sun.misc.Unsafe.park(Native Method)
            - parking to wait for  <0x0000000790f5dc40> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
            at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
            at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
            at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
    --
    "GC task thread#0 (ParallelGC)" prio=10 tid=0x000000001f287000 nid=0x7d30 runnable

    "GC task thread#1 (ParallelGC)" prio=10 tid=0x000000001f288800 nid=0x7d31 runnable

    "VM Periodic Task Thread" prio=10 tid=0x000000001f3d1000 nid=0x7d39 waiting on condition

    JNI global references: 579

This is the Code that happened problem:

    public class PageGetter {
    private static final Log log = LogFactory.getLog("serviceLogger");
    private static SyncBasicHttpParams httpParams = null;
    private HttpClient httpClient = null;
    private static PoolingClientConnectionManager connectionManager = null;
    private static Integer errorSleepTime = new Integer(PropertyGetter.getInstance().getProperty("errorpagesleeptime"));

    public String getFinalRedirectURL(String url) throws ClientProtocolException, IOException {
        if (url == null) {
            return null;
        }
        if (!url.trim().startsWith("http://")) {
            url = "http://" + url;
        }
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpget = new HttpGet(url);
        if (connectionManager == null || httpParams == null || this.httpClient == null) {
            this.initHttpManager();
        }
        this.httpClient.execute(httpget, localContext);
        HttpHost target = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
        String finalURL = target.toString();
        httpget.abort();
        return finalURL;
    }

    private void initHttpManager() {
        // Create and initialize HTTP parameters
        if (httpParams == null) {
            httpParams = new SyncBasicHttpParams();
            httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
            httpParams.setParameter(HTTP.CONTENT_ENCODING, "GBK");
            HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
        }
        if (connectionManager == null) {
            SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
            try {
                //Security Socket
                SSLContext ctx = SSLContext.getInstance("TLS");
                X509TrustManager tm = new X509TrustManager() {
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    @Override
                    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                    }
                };
                ctx.init(null, new TrustManager[] { tm }, null);
                SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
                schemeRegistry.register(new Scheme("https", 443, ssf));
            } catch (Exception e) {
                log.error("Fail to create connection manager " + e);
            }
            connectionManager = new PoolingClientConnectionManager(schemeRegistry);
        }
        this.httpClient = new DefaultHttpClient(connectionManager, httpParams);
        this.httpClient.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
        HttpClientParams.setCookiePolicy(this.httpClient.getParams(), CookiePolicy.BROWSER_COMPATIBILITY);
    }

    public String getPostPageContent(String url, List<NameValuePair> headers, List<NameValuePair> params) {
        String strPage = null;
        if (url == null) {
            return null;
        }
        if (!url.trim().startsWith("http")) {
            url = "http://" + url;
        }
        HttpPost httpPost = new HttpPost(url);
        HttpEntity entity = null;
        try {
            if (params != null) {
                httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
            }
            if (headers != null) {
                Iterator<NameValuePair> itrHeaders = headers.iterator();
                while (itrHeaders.hasNext()) {
                    NameValuePair header = itrHeaders.next();
                    httpPost.setHeader(header.getName(), header.getValue());
                }
            }
            HttpContext localContext = new BasicHttpContext();
            if (connectionManager == null || httpParams == null || this.httpClient == null) {
                this.initHttpManager();
            }
            HttpResponse response = this.httpClient.execute(httpPost, localContext);
            // get the response body as an array of bytes
            entity = response.getEntity();
            if (entity != null) {
                strPage = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            connectionManager = null;
            httpParams = null;
            this.httpClient = null;
            this.errorHandler(url, e);
        } finally {
            httpPost.abort();

            if (entity != null) {
                try {
                    EntityUtils.consume(entity);
                } catch (Exception e2) {
                    e2.printStackTrace();
                    log.error("Error when consume entity ", e2);
                }
            }
        }
        if (strPage != null) {
            Pattern pattern = Pattern.compile("\\s");
            Matcher matcher = pattern.matcher(strPage);
            strPage = matcher.replaceAll(" ");
            strPage = strPage.replaceAll("////", "");
        }
        return strPage;
    }

    private String getURL(String url, List<NameValuePair> headers) {
        if (headers == null) {
            return url;
        }
        Map<String, String> map = new HashMap<String, String>();
        if (url.contains("?")) {
            String str = url.substring(url.indexOf("?") + 1);
            url = url.substring(0, url.indexOf("?"));
            String[] strs = str.split("&");
            for (int i = 0; strs != null && i < strs.length; i++) {
                if (strs[i].contains("=")) {
                    String key = strs[i].substring(0, strs[i].indexOf("="));
                    String value = strs[i].substring(strs[i].indexOf("=") + 1);
                    map.put(key, value);
                }
            }
        }
        Iterator<NameValuePair> itrHeaders = headers.iterator();
        while (itrHeaders.hasNext()) {
            NameValuePair header = itrHeaders.next();
            if (header != null && header.getName() != null && header.getValue() != null) {
                try {
                    map.put(URLEncoder.encode(header.getName(), "UTF-8"), URLEncoder.encode(header.getValue(), "UTF-8"));
                } catch (Exception e) {
                    log.error("Can not parse parameter " + e);
                }
            }
        }
        if (map.keySet() == null) {
            return url;
        }
        Iterator<String> itr = map.keySet().iterator();
        String parameters = "";
        while (itr.hasNext()) {
            String key = itr.next();
            if (key != null && key.length() > 0) {
                parameters = parameters + key + "=" + map.get(key) + "&";
            }
        }
        if (parameters.length() > 0) {
            url = url + "?" + parameters;
        }
        return url;
    }

    private void errorHandler(String url, Exception e) {
        try {
            Thread.sleep(errorSleepTime);
            log.error("无法打开链接" + url + " sleep " + errorSleepTime + e);
        } catch (Exception e1) {
            log.error("Error sleeping " + errorSleepTime + e1);
        }
    }

    /**
     * Get page as string from URL
     *
     * @param url
     * @return
     */
    public String getPageContent(String url, List<NameValuePair> headers) {
        url = StringFilter.replaceUnicode(url);
        String strPage = null;
        if (url == null) {
            return null;
        }
        if (!url.trim().startsWith("http")) {
            url = "http://" + url;
        }
        if (url.endsWith("/")) {
            url = url.substring(0, url.lastIndexOf("/"));
        }
        HttpGet httpGet = null;
        HttpEntity entity = null;
        try {
            if (connectionManager == null || httpParams == null || this.httpClient == null) {
                this.initHttpManager();
            }
            url = this.getURL(url, headers);
            httpGet = new HttpGet(url);
            HttpContext localContext = new BasicHttpContext();
            HttpResponse response = this.httpClient.execute(httpGet, localContext);
            entity = response.getEntity();
            if (entity != null) {
                String charSet = ContentType.getOrDefault(entity).getCharset().toString();
                if (charSet == null) {
                    charSet = "UTF-8";
                }
                strPage = EntityUtils.toString(entity, charSet);
                strPage = strPage.replaceAll("\r", "");
                strPage = strPage.replaceAll("\n", "");
                //空格
                strPage = strPage.replaceAll("&nbsp;", "");
            }
        } catch (Exception e) {
            connectionManager = null;
            httpParams = null;
            this.httpClient = null;
            this.errorHandler(url, e);
        } finally {
            try {
                httpGet.abort();
            } catch (Exception e) {
                log.error("Error when httpclient aborting " + e);
            }

            if (entity != null) {
                try {
                    EntityUtils.consume(entity);
                } catch (Exception e2) {
                    e2.printStackTrace();
                    log.error("Error when consume entity ", e2);
                }
            }
        }
        return strPage;
    }

    public String getPageContentSms(String url, List<NameValuePair> headers) {
        url = StringFilter.replaceUnicode(url);
        String strPage = null;
        if (url == null) {
            return null;
        }
        if (!url.trim().startsWith("http")) {
            url = "http://" + url;
        }
        if (url.endsWith("/")) {
            url = url.substring(0, url.lastIndexOf("/"));
        }
        HttpGet httpGet = null;
        HttpEntity entity = null;
        try {
            if (connectionManager == null || httpParams == null || this.httpClient == null) {
                this.initHttpManager();
            }
            httpGet = new HttpGet(url);
            HttpContext localContext = new BasicHttpContext();
            HttpResponse response = this.httpClient.execute(httpGet, localContext);
            entity = response.getEntity();
            if (entity != null) {
                String charSet = ContentType.getOrDefault(entity).getCharset().toString();
                if (charSet == null) {
                    charSet = "UTF-8";
                }
                strPage = EntityUtils.toString(entity, charSet);
                strPage = strPage.replaceAll("\r", "");
                strPage = strPage.replaceAll("\n", "");
                strPage = strPage.replaceAll("&nbsp;", "");
            }
        } catch (Exception e) {
            connectionManager = null;
            httpParams = null;
            this.httpClient = null;
            this.errorHandler(url, e);
        } finally {
            try {
                httpGet.abort();
            } catch (Exception e) {
                log.error("Error when httpclient aborting " + e);
            }

            if (entity != null) {
                try {
                    EntityUtils.consume(entity);
                } catch (Exception e2) {
                    e2.printStackTrace();
                    log.error("Error when consume entity ", e2);
                }
            }
        }
        return strPage;
    }

    public List<NameValuePair> getDefaultHeaders() {
        List<NameValuePair> headers = new ArrayList<NameValuePair>();
        BasicNameValuePair nameValuePair = new BasicNameValuePair("Accept",
                "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("Accept-Charset", "GBK,utf-8;q=0.7,*;q=0.3");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("Accept-Encoding", "GBK,utf-8;q=0.7,*;q=0.3");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("Accept-Language", "zh-CN,zh;q=0.8");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("Cache-Control", "max-age=0");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("Connection", "keep-alive");
        headers.add(nameValuePair);
        nameValuePair = new BasicNameValuePair("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19");
        headers.add(nameValuePair);
        return headers;
    }

    public String getTaobaoContent(List<NameValuePair> params) {
        return this.getPageContent(Constant.TAOBAO_API_URL, params);
    }
解决方案

We were seeing very similar issue when using HttpClient with Jersey. Threads were blocked waiting for connection.

In our case the connection pool got depleted when we encountered 40x errors in our GET requests.

The reason was that the connections were never freed back to the pool unless we actually read the response body ( which we did not in the cases when we got client error codes).In your source code it seems you just throw the ClientProtocolException without reading the response.. it might be similar..

这篇关于使用Java的Apache PoolingClientConnectionManager泄漏内存,如何解决呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 08:33