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
Deregister JDBC drivers during undeploy of a war deployment #21221
Comments
Sorry, it is really nothing special. https://github.com/BenICE/exampleMemoryLeak <-- hope this is the right way to share it. |
Thanks for the sample, @BenICE. Unfortunately, I don't think there's much that we can do about this. H2 automatically registers itself in the static initialiser of A further complication is that Spring Boot itself does not load I think you have a few options:
FWIW, I would implement that last of these by overriding @Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(new ServletContextListener() {
@Override
public void contextDestroyed(ServletContextEvent sce) {
org.h2.Driver.unload();
}
});
super.onStartup(servletContext);
} I've resorted to using internal API to avoid potential problems with H2's internal state getting out of sync with that of |
Shit sorry...I lead you on a goose chase. I just took H2 as an example. But you have the same behaviour as well with e.g. the maria DB driver. In my opinion it concerns all JDBC drivers. |
Ideally, JDBC drivers would ship with a Failing that, fixing the problem at the container level is the next best option, but it limits the impact of the fix to those that are using a particular container. Lastly, we could fix it in Spring Boot by adding code that mimics what Tomcat does in @Override
public void contextDestroyed(ServletContextEvent sce) {
for (Driver driver: Collections.list(DriverManager.getDrivers())) {
if (driver.getClass().getClassLoader() == sce.getServletContext().getClassLoader()) {
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
// Continue
}
}
}
}
The code above would break any I'm wavering a bit on this one now. Let's see what the rest of the team thinks. |
Thanks a lot for adding this feature to the base! |
Hi,
following up on the registration of JDBC drivers in Spring Boot (especially #2612).
As I can see it, no Spring Boot Application (e.g. 2.2.6) deregisters its JDBC driver.
Standard Spring Boot created with Spring boot initializr & In Memory H2 database, will leave its driver behind, which leads to a memory leak as the class loader cannot be GCed.
Why is there no huge outcry?
I guess these are the most standard cases, but if you run it in a JBoss environment you will not have much fun as the server will quickly rise an OOM after some deployments.
Workaround (which I deployed) is to deregister the driver in a context listener, when the context is destroyed (much like https://stackoverflow.com/questions/3320400/to-prevent-a-memory-leak-the-jdbc-driver-has-been-forcibly-unregistered/23912257#23912257).
Sure, we could relay on the Tomcat memory leak protection or deploy the database driver in the application server, but I would assume a War-file produced by Spring Boot should run everywhere.
What is your take on it?
Best
The text was updated successfully, but these errors were encountered: