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: Spring ApplicationContext caches are not cleared as expected in integration tests if beans are lazy initialized As expected, Spring keeps the last 32 contexts in memory for potential re-use. However the individual contexts seem quite large: Spring ApplicationContext caches are not cleared as expected in integration tests if beans are lazy initialized 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?

Comment From: wilkinsona

Thanks for the report. While spring.main.lazy-initialization is a Spring Boot feature, it just sets the lazy init flag on bean definitions, something that could be done without involving Boot. As such, I think this would be better addressed in Spring Framework as it's responsible both for the caching and the test class initialization. We'll transfer the issue so that the Framework team can take a look.

Comment From: snicoll

I can see how lazy initialization can defeat that cache to be cleared. I don't know if this is something we can fix automatically, or if it's something we should improve on a case-by-case basis. Having a hook point in the TCF when it parks the context in the cache could be a good place to improve the current situation.

Comment From: snicoll

@bgK if you have a chance to test the milestone, that would be very much appreciated.