Java 记录大字符串会导致OutOfMemoryError

Java 记录大字符串会导致OutOfMemoryError,java,spring,performance,logging,logback,Java,Spring,Performance,Logging,Logback,我的springbootweb应用程序连接到许多外部服务,它需要将服务的所有请求和响应写入日志文件 import org.slf4j.Logger; import org.slf4j.LoggerFactory; .... private static final Logger LOG = LoggerFactory.getLogger(RequestLoggingClientRequestInterceptor.class); ... ClientHttpResponse respon

我的springbootweb应用程序连接到许多外部服务,它需要将服务的所有请求和响应写入日志文件

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

....

private static final Logger LOG = LoggerFactory.getLogger(RequestLoggingClientRequestInterceptor.class);

...

ClientHttpResponse response = execution.execute(request, body);
InputStream s = response.getBody();
String loggingResponseBody = new String(ByteStreams.toByteArray(s), Charset.forName("UTF-8"));
LOG.info("response status code: {}, response headers: {}, response body: {}",
            response.getStatusCode(),
            response.getHeaders(),
            loggingResponseBody);
我对日志引擎使用Logback。下面的代码用于将响应消息打印到日志文件

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

....

private static final Logger LOG = LoggerFactory.getLogger(RequestLoggingClientRequestInterceptor.class);

...

ClientHttpResponse response = execution.execute(request, body);
InputStream s = response.getBody();
String loggingResponseBody = new String(ByteStreams.toByteArray(s), Charset.forName("UTF-8"));
LOG.info("response status code: {}, response headers: {}, response body: {}",
            response.getStatusCode(),
            response.getHeaders(),
            loggingResponseBody);
此代码存在性能问题。它消耗高CPU,导致高延迟,并且在响应消息非常大的某些情况下,在执行
新字符串(ByteStreams.toByteArray,Charset.forName(“UTF-8”))时会导致
OutOfMemoryError

原因:java.lang.OutOfMemoryError:java堆空间
在java.lang.StringCoding.decode(StringCoding.java:215)
位于java.lang.String。(String.java:463)
位于java.lang.String。(String.java:515)
在
请注意,我没有将字符串解码为“UTF-8”的具体要求,我这样做是因为
string
类的构造函数建议这样做


请建议如何改进代码以解决性能问题。我已经尝试了
AsyncAppender
,虽然它有助于延迟,但我遇到了
OutOfMemoryError
必须关闭ClientHttpResponse(按指定),而
ByTestStreams.toByteArray
没有(按指定)


所以这可能只是一个资源泄漏。代码似乎很脆弱,因为必须确保响应是UTF-8文本,并且不超过无意义的兆字节。

您可以做一些类似的事情,这是一个从所有服务收集和打印日志的服务吗?导致OOM的响应体有多大?你是对的,这是一个资源泄漏问题。非常感谢。
try (InputStream s = response.getBody()) {
    LOG.info("response status code: {}, response headers: {}, response body:",
            response.getStatusCode(),
            response.getHeaders());
    String loggingResponseBody = new String(ByteStreams.toByteArray(s),
            StandardCharsets.UTF_8);
    LOG.info(loggingResponseBody); // One param means no format with {}
}