我在使用httpclients 4.5.4时遇到了问题。 当我关闭与我的连接相关的所有内容时,java GC无法收集PoolingHttpClientConnectionManager对象。 因此,当应用程序运行大约1个月时,我遇到了一个OOM异常。 我的代码与https://hc.apache.org/httpcomponents-client-4.5.x/httpclient/examples/org/apache/http/examples/client/ClientConnectionRelease.java中的示例相同。 并且Java GC也无法收集InternalHttpClient对象。 下面有我的代码,是否有任何对象包含两个类的引用?
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 :(得分:0)
我不能告诉你为什么你的内存耗尽,但我可以告诉你,以这种方式做到这一点并不是一个好主意(尽管你使用了“推荐方式”)。
我正在使用版本4.5.3中的CloseableHttpClient
和PoolingHttpClientConnectionManager
,我从不关闭它们(它们都在单例中分配一次并用于所有请求)。我的应用程序目前正在运行,因为可能每个月只执行一次请求(不是很多)。
请注意,为每个连接创建新客户端与为每次旅行购买新车一样高效。