2017-12-28 4 views
1

Ich habe ein Problem, während ich httpclients 4.5.4 verwende. Wenn ich alles schließe, was zu meiner Verbindung gehört, können die PoolingHttpClientConnectionManager-Objekte nicht von Java GC gesammelt werden. So wie die Anwendung für etwa 1 Monat läuft, habe ich eine OOM-Ausnahme. Mein Code ist der gleiche wie in Beispiel https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.java. Und InternalHttpClient Objekte können auch nicht von Java GC gesammelt werden. Es gibt meinen Code unten, gibt es irgendwelche Objekte, die die Referenzen der beiden Klassen enthalten?Wie man PoolingHttpClientConnectionManager in httpclient4.5.4 freigibt

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

Ich bekam die Antwort, eine andere Klasse verwendet PoolingHttpClientConnectionManager und hat sie nicht freigegeben. Ich habe sie in einer matten Speicherkartenanalyse gefunden. Danke. –

Antwort

0

Ich kann Ihnen nicht sagen, warum Sie nicht genügend Arbeitsspeicher laufen, aber ich kann Ihnen sagen, dass es keine gute Idee ist es auf diese Weise zu tun (obwohl Sie eine „empfohlene Methode“ verwendet wird).

Ich verwende und PoolingHttpClientConnectionManager von Version 4.5.3 und ich schließe sie nie (sie sind beide einmal in einem Singleton zugewiesen und für alle Anfragen verwendet). Meine Anwendung läuft derzeit seit ungefähr einem Monat und macht ungefähr eine Anfrage pro Sekunde (nicht wirklich viel).

Beachten Sie, dass das Erstellen eines neuen Clients für jede Verbindung ungefähr so ​​effizient ist wie der Kauf eines neuen Autos für jede Fahrt.

Verwandte Themen