Description
The test suite for our application using Spring Boot 3.1.1 recently started failing with OutOfMemoryError
.
Analyzing the contents of the heap shows the following:
As expected, Spring keeps the last 32 contexts in memory for potential re-use. However the individual contexts seem quite large:
The resource cache for DefaultResourceLoader
is responsible for much of the memory usage. It seems like this cache is intended to be cleared when the context initialization completes. When using lazy initialization, the initialization of the test class can cause the classpath to be scanned afterwards, filling the cache once again.
This is a minimal reproducer for such a case:
package org.example;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest
@AutoConfigureMockMvc
@EnableAutoConfiguration
@TestPropertySource(properties = {
"spring.main.lazy-initialization=true"
})
public class ReproTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private DefaultResourceLoader defaultResourceLoader;
@Test
public void applicationContextResourceCacheShouldBeEmpty() {
assertTrue(defaultResourceLoader.getResourceCache(MetadataReader.class).isEmpty());
}
@SpringBootConfiguration
public static class ReproConfiguration {
}
}
Should Spring ensure the resource cache is emptied when running tests to reduce memory usage?