Skip to content

ConfigurationClassEnhancer prevents BeanFactory from being GCd [SPR-7901] #12556

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

Closed
spring-projects-issues opened this issue Jan 21, 2011 · 9 comments
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: bug A general bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Jan 21, 2011

Tommy Becker opened SPR-7901 and commented

We're experiencing OOM errors during unit test runs. We make fairly heavy use of Java based context configuration in our application as well as the tests. Upon investigation, I see that there are a number of ApplicationContext instances still referenced on the heap that should be collectable. It appears that the way the ConfigurationClassEnhancer is registering its BeanMethodInterceptor with the CGLIB generated subclass is the problem. In #10601, this was changed from Enhancer.registerCallbacks() to Enhancer.registerStaticCallbacks() to work around the fact that the former only applies the advice when method calls originate from the same thread that registered the callback. However using the static callback mechanism results in a static reference from the generated subclass to the interceptor, which in turn keeps a reference to the BeanFactory. So the BeanFactory is never eligible for GC, even after its been closed. Although problems running unit tests reveled the problem, we're most likely experiencing it at runtime as well since our application does close contexts and start new ones dynamically in response to some events.

As a potential fix, it would be nice if the BeanMethodInterceptor could receive a callback itself when the BeanFactory it references is closed, so it can then unregister itself from the CGLIB proxy. Alternatively, perhaps a WeakReference to the BeanFactory could be used from the interceptor.


Affects: 3.0.3

Attachments:

Issue Links:

Referenced from: commits d2faef4, 43676bd

5 votes, 3 watchers

@spring-projects-issues
Copy link
Collaborator Author

Tommy Becker commented

I've investigated this some more and found some more information. The use of static callbacks is not the root problem, as even the non-static callback mechanism uses ThreadLocals, and since the threads live for the lifetime of the JVM, the problem still exists. The root issue is the callbacks, regardless of how they are registered, need to be cleared when the context is destroyed. I've managed to get this to work in the interim by adding a @PreDestroy method in the configuration class itself which simply calls Enhancer.registerStaticCallbacks(this.getClass(), null); This is obviously cumbersome, but it does seem to work. However it seems like this is clearly something Spring should handle for you.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Thanks for the detailed investigation and notes, Tommy. I'll take a look.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

CGLIB-enhanced @Configuration subclasses now implement DisposableBean
such that Enhancer.registerStaticCallbacks(subclass, null) is invoked
on container shutdown. This ensures that garbage collection can work
properly and avoids memory consumption issues for applications that
create and destroy many application contexts within the same JVM.

Tommy, I'm leaving this open in a 'Waiting for Feedback' state as I'd like to hear from you as to whether everything works as expected.  Would you mind grabbing tonight's snapshot and giving it a try?

@spring-projects-issues
Copy link
Collaborator Author

Tommy Becker commented

Thanks for the fix Chris. Will try and take a look at it soon, although even with the workaround I described in place, we were still having OOM issues, causing me to open https://jira.springsource.org/browse/SPR-8008 So it will take a little more work for me to verify this specific fix...

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

OK, I'll leave it in 'Waiting for Feedback', then. Verification will be much appreciated. These issues can be elusive, as you know too well :) Note that we're targeting M2 for release within the next 2-3 weeks, to give you a timeframe.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

@Tommy - any update on verifying this fix?

@spring-projects-issues
Copy link
Collaborator Author

Tommy Becker commented

@Chris, we've changed our build process such that I may not be able to replicate the issue, but I'll at least take a look at the fix. Can you provide a link to where I can get a build and source with this included?

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

<repository>
  <id>spring-maven-snapshot</id>
  <snapshots><enabled>true</enabled></snapshots>
  <name>Spring Framework Maven snapshot repository</name>
  <url>http://maven.springframework.org/snapshot</url>
</repository>

If you're not using Maven, you can find the jars here: http://bit.ly/hfy4KI. Note that the only module affected by this change was spring-context, but other changes may require pulling down other dependent modules. The change was committed on March 14th, so anything after March 15th should include the change.

Grab the latest to be safe, but it will also include the most dependecies on changes in other modules.

@spring-projects-issues
Copy link
Collaborator Author

Chris Beams commented

Resolving as fixed for M2. The fix has been in for some time, and we've not heard further complaints on this front since. @Tommy, please re-open this issue at will if your verifications turn up negative.

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

1 participant