Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbstractApplicationContext.refresh() leaves bean resources uncleaned when SmartInitializationSingleton throws a non BeansException #28878

Closed
pfoermer opened this issue Jul 27, 2022 · 2 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@pfoermer
Copy link

Affects: Tested with 5.3.22 and 5.2.20.RELEASE

Problem description:
For some configuration issues during application context creation the AbstractApplicationContext.refresh()
method is not executing the catch(BeansException ex)/clean block. In this cleanup-block already created beans are getting destroyed by calling their close method. Especially for JUnit 5 annotated classes with @ExtendWith(SpringExtension.class)
this may cause potential resource leaks as for every test method depending on a faulty context the context will be tried to recreated without previous clean-up of resources which stay alive.

In a real world project the faulty, not destroyed, test contexts consumed all database connections of a shared DBMS as the created Hikari CP DataSource Pool was not closed/freed by AbstractApplicationContext.refresh().
At the end the amount of not cleaned up test contexts also caused an OutOfMemoryError as Hikari CP makes use of background threads and so references survive the garbage collector for the no longer used AbstractApplicationContext.

I attached a sample project
test-app.zip with
two "test samples/cases" (src/test/java/app) which will both cause a not successful application context creation but with two different behaviours of the clean-up:

  1. For "LeakTest" the close method of "DummyDbcp" will not be called by AbstractApplicationContext, also the bean was created in the application context. The text "Pool closed, db connections released" is not printed to STDOUT via logger.
  2. For "NonCausingLeakTest" the close method of "DummyDbcp" will be called by AbstractApplicationContext, preventing against resource leaks. The text "Pool closed, db connections released" is printed to STDOUT via logger.

The pom.xml of the project makes use of spring-boot-starter's, but only spring-framework components are really used.

Best regards,
Philipp Förmer

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jul 27, 2022
@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Jul 27, 2022
@snicoll
Copy link
Member

snicoll commented Oct 2, 2023

Thanks for the sample and sorry it got overlooked thus far.

@jhoeller I am a bit confused as why already-created beans would not be closed on a failed context. I like the sample as it's bare bone but I wonder if I am missing something. Perhaps a companion to #20028?

@snicoll snicoll added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 3, 2023
@snicoll snicoll added this to the 6.1.x milestone Oct 3, 2023
@snicoll
Copy link
Member

snicoll commented Oct 3, 2023

So it turns out to be quite an interesting review of AbstractApplicationContext#refresh. Refresh on catch BeansException as this is what it's expecting anything that would be thrown as part of the context refresh would have been wrapped in an exception of that type, except the afterSingletonInstantied callback.

Discussing with @jhoeller we were wondering if doing that there would be an option but, in retrospect, we think changing the catch block to handle any RuntimeException would be much future proof and will make sure that beans that have already been created to be reclaimed.

Thanks again for the sample @pfoermer

@snicoll snicoll changed the title AbstractApplicationContext.refresh() leaves bean resources uncleaned for special cases of faulty start-up AbstractApplicationContext.refresh() leaves bean resources uncleaned when SmartInitializationSingleton throws a non BeansException Oct 3, 2023
@snicoll snicoll self-assigned this Oct 13, 2023
snicoll added a commit to snicoll/spring-framework that referenced this issue Oct 13, 2023
This commit updates AbstractApplicationContext#refresh to handle any
runtime exceptions, not only BeansExceptions. If the exception is not
a BeansException, it is wrapped in an ApplicationContextException.

Closes spring-projectsgh-28878
@snicoll snicoll modified the milestones: 6.1.x, 6.1.0-RC2 Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Projects
None yet
Development

No branches or pull requests

4 participants