2017-12-28 36 views
1

httpclients 4.5.4を使用しているときに問題が発生しました。 接続に関連するすべてのものを閉じると、PoolingHttpClientConnectionManagerオブジェクトはjava GCによって収集できません。 アプリケーションが約1ヶ月間実行されるため、OOM例外が発生しました。 私のコードはhttps://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.javaの例と同じです。 InternalHttpClientオブジェクトは、Java GCでも収集できません。 以下のコードがあります.2つのクラスの参照を保持するオブジェクトはありますか?httpclient4.5.4でPoolingHttpClientConnectionManagerを解放する方法

import java.io.BufferedReader; 
    import java.io.File; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.util.Map; 

    import org.apache.http.HttpStatus; 
    import org.apache.http.client.methods.CloseableHttpResponse; 
    import org.apache.http.client.methods.HttpPost; 
    import org.apache.http.entity.ContentType; 
    import org.apache.http.entity.mime.MultipartEntityBuilder; 
    import org.apache.http.entity.mime.content.FileBody; 
    import org.apache.http.entity.mime.content.StringBody; 
    import org.apache.http.impl.client.CloseableHttpClient; 
    import org.apache.http.impl.client.HttpClients; 
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 

    public class HttpUtil { 

     private static Logger logger = LoggerFactory.getLogger(HttpUtil.class); 

     /** 
     * Http post请求 
     */ 
     public static String doHttpPost(String postUrl, Map<String, String> headers, 
       Map<String,String> params,String filePath) { 
      try { 
       CloseableHttpClient httpClient = HttpClients.createDefault(); 
       try { 
        HttpPost post = getHttpPost(postUrl, headers, params, filePath); 
        CloseableHttpResponse response = httpClient.execute(post); 
        try { 
         InputStream inputStream = null; 
         InputStreamReader inputStreamReader = null; 
         BufferedReader bufferedReader = null; 
         if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 
          try { 
           inputStream = response.getEntity().getContent(); 
           inputStreamReader = new InputStreamReader(inputStream); 
           bufferedReader = new BufferedReader(inputStreamReader); 
           return bufferedReader.readLine(); 
          }catch (Exception e) { 
           logger.warn("do http post fail : ", e); 
          }finally { 
           if (bufferedReader != null) { 
            logger.info("release bufferedReader: " + filePath); 
            bufferedReader.close(); 
           } 
           if (inputStreamReader != null) { 
            logger.info("release inputStreamReader: " +filePath); 
            inputStreamReader.close(); 
           } 
           if (inputStream != null) { 
            logger.info("release inputStream: " +filePath); 
            inputStream.close(); 
           } 
          } 
         } 
        } catch (Exception e) { 
         logger.warn("do http post fail: ", e); 
        } finally { 
         if (response != null) { 
          logger.info("release response: " + filePath); 
          response.close(); 
         } 
         if (post != null) { 
          logger.info("release HttpPost: " + filePath); 
          post.releaseConnection(); 
         } 
        } 
       } catch (Exception e) { 
        logger.warn("do http post fail: ", e); 
       } finally { 
        if (httpClient != null) { 
         logger.info("release httpClient: " + filePath); 
         httpClient.close(); 
         logger.info("release connectionManager: " + filePath); 
         httpClient.getConnectionManager().shutdown(); 
        } 
       } 
      } catch (Exception e) { 
       logger.warn("do http post fail: ", e); 
      } 

      return ""; 
     } 

     private static HttpPost getHttpPost(String postUrl, Map<String, String> headers, 
       Map<String, String> params, String filePath) { 
      HttpPost post = new HttpPost(postUrl); 
      String[] headerKeys = headers.keySet().toArray(new String[headers.keySet().size()]); 
      for (String key : headerKeys) { 
       post.setHeader(key, headers.get(key)); 
      } 

      FileBody fileBody = new FileBody(new File(filePath)); 
      MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); 
      multipartEntityBuilder.addPart("express_image", fileBody); 

      String[] paramKeys = params.keySet().toArray(new String[params.keySet().size()]); 
      for (String key : paramKeys) { 
       StringBody valueBody = new StringBody(params.get(key), ContentType.TEXT_PLAIN); 
       multipartEntityBuilder.addPart(key, valueBody); 
      } 

      post.setEntity(multipartEntityBuilder.build()); 
      return post; 
     } 

    } 
+0

私は答えを得ました。別のクラスはPoolingHttpClientConnectionManagerを使用し、それらを解放しませんでした。私はマットメモリマップアナライザでそれらを見つけました。 –

答えて

0

あなたはメモリが不足し、なぜ私はあなたを伝えることはできませんが、(あなたは、「推奨される方法」を使用しているにもかかわらず)、私はそれがこのようにそれを行うには良いアイデアだしないことを、あなたに伝えることができます。

バージョン4.5.3のCloseableHttpClientPoolingHttpClientConnectionManagerを使用していますが、決して閉じません(シングルトンで1回割り当てられ、すべてのリクエストに使用されます)。私のアプリケーションは、おそらく1ヶ月あたり約1回のリクエスト(実際はあまりありません)を行っているからです。

各接続ごとに新しいクライアントを作成することは、各旅行ごとに新しい車を購入するほど効率的であることに注意してください。

関連する問題