java.lang.OutOfMemoryError:java堆空间(JUnit测试)



我有一个类,我使用输入流,然后将其转换为字符串。我还有一个Junit测试,在那里我得到了异常"java.lang.OutOfMemoryError:java堆空间",我知道问题是我在测试中出现了内存泄漏,但我不知道如何修复它。也许有人知道怎么做?

我的班级:

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);
}
}
}

我的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)

您的模拟输入是一个无限长的NUL(零(字节流。在某个时刻,有人试图将其全部读取到内存中,这当然会让你耗尽内存,因为它是无限长的:

final InputStream inputStream = new InputStream()
{
@Override
public int read()
{
return 0;
}
};

一个快速的解决方案是将其限制在已知的大小,如100字节

final InputStream inputStream = new ByteArrayInputStream(new byte[100]);

相关内容

  • 没有找到相关文章

最新更新