I upgraded my project from SpringBoot 3.5.14 / Spring 6.2.18 to Spring Boot 4.0.6 / Spring 7.0.7
When I run my test suite, it fails due to OOM:
[ERROR] See /.../target/surefire-reports for the individual test results.
[ERROR] See dump files (if any exist) [date].dump, [date]-jvmRun[N].dump and [date].dumpstream.
[ERROR] There was an error in the forked process
[ERROR] java.lang.OutOfMemoryError: Java heap space
[ERROR] org.apache.maven.surefire.booter.SurefireBooterForkException: There was an error in the forked process
[ERROR] java.lang.OutOfMemoryError: Java heap space
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.fork(ForkStarter.java:631)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:285)
[ERROR] at org.apache.maven.plugin.surefire.booterclient.ForkStarter.run(ForkStarter.java:250)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeProvider(AbstractSurefireMojo.java:1347)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.executeAfterPreconditionsChecked(AbstractSurefireMojo.java:1145)
[ERROR] at org.apache.maven.plugin.surefire.AbstractSurefireMojo.execute(AbstractSurefireMojo.java:979)
[ERROR] at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:126)
This OOM happens first in our CI (our runners have 4GB of total RAM). I can reproduce it locally by defining a parameter 'Xmx900m' for the forked JVM.
In production, the real Spring Boot application (version 3.5.x) is working perfectly with a Xmx500m.
The forked process is consuming more and more memory. This is the graph from gc logs of the test fork JVM.
I dump the memory file on the OOM. This is the first analysis I do:
Main problem: 2, 3, 4, and 5
The issue 2, 3, 4 and 5, 123m for each AnnotationConfigApplicationContext.
In the JVM, I have 5 org.springframework.context.annotation.AnnotationConfigApplicationContext that retain 500m:
2nd issue DefaultListableBeanFactory
The number 1 suspect is 11 instances of org.springframework.beans.factory.support.DefaultListableBeanFactory.
This is an overview of our test:
| Module |
Classes |
@Test methods |
SpringBoot |
JpaTest |
Mockito |
SpringExt |
Plain |
| Total |
853 |
6 477 |
49 |
82 |
309 |
101 |
312 |
The full Mockito test doesn't rely on anything. The JPA & SpringBootTest test rely on test container (local stack & postgresql).
Do you have an idea for the origin of the 11 instances of DefaultListableBeanFactory?
And why do 4 AnnotationConfigApplicationContexts retain so much memory (and the last one very few), all of them loaded with the same class loader?
I can't share the heap dump, but I can do query on it if it's useful.
Are they not supposed to be singleton?
May be related to #34279.
I upgraded my project from SpringBoot 3.5.14 / Spring 6.2.18 to Spring Boot 4.0.6 / Spring 7.0.7
When I run my test suite, it fails due to OOM:
This OOM happens first in our CI (our runners have 4GB of total RAM). I can reproduce it locally by defining a parameter 'Xmx900m' for the forked JVM.
In production, the real Spring Boot application (version 3.5.x) is working perfectly with a
Xmx500m.The forked process is consuming more and more memory. This is the graph from gc logs of the test fork JVM.
I dump the memory file on the OOM. This is the first analysis I do:
Main problem: 2, 3, 4, and 5
The issue 2, 3, 4 and 5, 123m for each
AnnotationConfigApplicationContext.In the JVM, I have 5
org.springframework.context.annotation.AnnotationConfigApplicationContextthat retain 500m:2nd issue DefaultListableBeanFactory
The number 1 suspect is 11 instances of
org.springframework.beans.factory.support.DefaultListableBeanFactory.This is an overview of our test:
@TestmethodsThe full Mockito test doesn't rely on anything. The JPA & SpringBootTest test rely on test container (local stack & postgresql).
Do you have an idea for the origin of the 11 instances of
DefaultListableBeanFactory?And why do 4 AnnotationConfigApplicationContexts retain so much memory (and the last one very few), all of them loaded with the same class loader?
I can't share the heap dump, but I can do query on it if it's useful.
Are they not supposed to be singleton?
May be related to #34279.