[英]java.lang.OutOfMemoryError: Java heap space (JUnit test)
I have a class,which i use input stream and then conver it to string.我有一个类,我使用输入流,然后将其转换为字符串。 Also i have a Junit test,where i get the exception " java.lang.OutOfMemoryError: Java heap space",I know that the problem is that I have a memory leak in the test, but I don't understand how to fix it.Maybe someone know how to do it?
另外我有一个 Junit 测试,在那里我得到异常“java.lang.OutOfMemoryError:Java 堆空间”,我知道问题是我在测试中有内存泄漏,但我不明白如何解决它.也许有人知道怎么做?
My class:我的课:
public class IntegrationMonitoringHttpInterceptor implements ClientHttpRequestInterceptor
{
private static final Logger LOG = LoggerFactory.getLogger(IntegrationMonitoringHttpInterceptor.class);
@Resource
private IntegrationMessageService integrationMessageService;
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] bytes, final ClientHttpRequestExecution clientHttpRequestExecution) throws IOException
{
final String requestMethod = request.getMethod().toString();
final String requestURI = request.getURI().toString();
final String requestHeaders = request.getHeaders().toString();
final String requestBody = new String(bytes, StandardCharsets.UTF_8);
final String requestMessageBody = requestMethod + "\n" + requestURI + "\n" + requestHeaders + "\n" + requestBody;
final IntegrationMessageBatchModel batch = saveRequest(requestURI, requestMessageBody);
try
{
final ClientHttpResponse response = clientHttpRequestExecution.execute(request, bytes);
final String responseStatusCode = response.getStatusCode().toString();
final String responseStatusText = response.getStatusText();
final String responseHeaders = response.getHeaders().toString();
final InputStream responseInputStream = response.getBody();
final String responseBody = IOUtils.toString(responseInputStream, StandardCharsets.UTF_8.name()); //in the test, a memory leak occurs here
IOUtils.closeQuietly(responseInputStream);
responseInputStream.close();
final String responseMessageBody = responseStatusCode + "\n" + responseStatusText + responseHeaders + "\n" + responseBody;
saveResponse(responseMessageBody, batch, requestURI);
return response;
}
catch (Exception exception)
{
integrationMessageService.createMessageInBatch(exception.getMessage(), batch);
LOG.warn("Cannot execute request due to unexpected error", exception);
throw exception;
}
}
private IntegrationMessageBatchModel saveRequest(final String requestURI, final String requestMessageBody)
{
try
{
IntegrationMessageBatchModel integrationMessageBatchModel = integrationMessageService.createBatch(IntegrationExchangeType.HTTP, requestURI);
integrationMessageService.createMessageInBatch(requestMessageBody, integrationMessageBatchModel);
return integrationMessageBatchModel;
}
catch (Exception exception)
{
LOG.warn("Cannot save message due to unexpected error", exception);
return null;
}
}
private void saveResponse(final String response, final IntegrationMessageBatchModel batchModel, final String requestURI)
{
try
{
if (batchModel != null)
{
integrationMessageService.createMessageInBatch(response, batchModel);
}
else
{
IntegrationMessageBatchModel integrationMessageBatchModel = integrationMessageService.createBatch(IntegrationExchangeType.HTTP, requestURI);
integrationMessageService.createMessageInBatch(response, integrationMessageBatchModel);
}
}
catch (Exception exception)
{
LOG.warn("Cannot save message due to unexpected error", exception);
}
}
}
My JUnit test:我的 JUnit 测试:
@RunWith(MockitoJUnitRunner.class)
@UnitTest
public class IntegrationMonitoringHttpInterceptorTest
{
@Rule
public ExpectedException thrown = ExpectedException.none();
@Mock
private IntegrationMessageService integrationMessageService;
@Mock
private HttpRequest httpRequest;
@Mock
private ClientHttpRequestExecution clientHttpRequestExecution;
@Mock
private ClientHttpResponse clientHttpResponse;
@InjectMocks
private IntegrationMonitoringHttpInterceptor integrationMonitoringHttpInterceptor = new IntegrationMonitoringHttpInterceptor();
@Test
public void intercept() throws Exception
{
final String body = "http message";
final URI uri = new URI("http://headers.jsontest.com/");
final InputStream inputStream = new InputStream()
{
@Override
public int read()
{
return 0;
}
};
when(httpRequest.getURI()).thenReturn(uri);
when(httpRequest.getMethod()).thenReturn(HttpMethod.POST);
when(httpRequest.getHeaders()).thenReturn(new HttpHeaders());
when(clientHttpRequestExecution.execute(httpRequest, body.getBytes(StandardCharsets.UTF_8))).thenReturn(clientHttpResponse);
when(clientHttpResponse.getStatusCode()).thenReturn(HttpStatus.OK);
when(clientHttpResponse.getStatusText()).thenReturn("OK");
when(clientHttpResponse.getHeaders()).thenReturn(new HttpHeaders());
when(clientHttpResponse.getBody()).thenReturn(inputStream);
when(integrationMessageService.createBatch(eq(IntegrationExchangeType.HTTP), eq(uri.toString())))
.thenReturn(new IntegrationMessageBatchModel());
when(integrationMessageService.createMessageInBatch(eq(body), any(IntegrationMessageBatchModel.class)))
.thenReturn(new IntegrationMessageModel());
when(integrationMessageService.createMessageInBatch(contains(body), any(IntegrationMessageBatchModel.class)))
.thenReturn(new IntegrationMessageModel());
integrationMonitoringHttpInterceptor.intercept(httpRequest, body.getBytes(StandardCharsets.UTF_8), clientHttpRequestExecution);
verify(clientHttpRequestExecution, times(1)).execute(httpRequest, body.getBytes(StandardCharsets.UTF_8));
verify(integrationMessageService, times(1)).createBatch(eq(IntegrationExchangeType.HTTP), eq(uri.toString()));
verify(integrationMessageService, times(2)).createMessageInBatch(anyString(), any(IntegrationMessageBatchModel.class));
}
Stacktrace:堆栈跟踪:
java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2367)
at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:130)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:114)
at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:535)
at java.lang.StringBuilder.append(StringBuilder.java:204)
at org.apache.commons.io.output.StringBuilderWriter.write(StringBuilderWriter.java:138)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:2002)
at org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1980)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1957)
at org.apache.commons.io.IOUtils.copy(IOUtils.java:1907)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:778)
at org.apache.commons.io.IOUtils.toString(IOUtils.java:803)
at core.interceptors.IntegrationMonitoringHttpInterceptor.intercept(IntegrationMonitoringHttpInterceptor.java:48)
at core.interceptors.IntegrationMonitoringHttpInterceptorTest.intercept(IntegrationMonitoringHttpInterceptorTest.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:110)
at org.junit.rules.RunRules.evaluate(RunRules.java:18)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
Your mock input is an infinitely long stream of NUL (zero) bytes.您的模拟输入是无限长的 NUL(零)字节流。 At some point there's an attempt to read all of it into memory, which of course makes you run out of memory because it's infinitely long:
在某些时候,尝试将所有内容读入内存,这当然会使您耗尽内存,因为它无限长:
final InputStream inputStream = new InputStream()
{
@Override
public int read()
{
return 0;
}
};
A quick fix is to limit it to a known size like 100 bytes快速解决方法是将其限制为已知大小,例如 100 字节
final InputStream inputStream = new ByteArrayInputStream(new byte[100]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.