Explain Codes LogoExplain Codes Logo

To prevent a memory leak, the JDBC Driver has been forcibly unregistered

sql
connection-pooling
jdbc-driver
memory-leak
Anton ShumikhinbyAnton Shumikhin·Mar 8, 2025
TLDR

To prevent memory leaks with JDBC, it's crucial you deregister drivers as part of your shutdown routine:

for (Driver driver : Collections.list(DriverManager.getDrivers())) { DriverManager.deregisterDriver(driver); }

This neat little routine loops through all your loaded JDBC drivers and deregisters every single one of them. This is your ticket out of resource-retentionville, especially in the land of servlet containers hot-redeploying applications.

The Nitty Gritty: Memory Leaks & JDBC Drivers

When you redeploy a web app, it's expected that the old version and its classes go gently into that good night. But if you have a JDBC driver, loaded up by your web application class loader, it registers itself with the DriverManager and might not take the hint that it's time to leave. This stubbornness results in a memory leak, as previous deployment classes are left hanging with nowhere to go.

Best Practices for Dealing with JDBC Drivers

Dive into connection pooling

To manage your database connections in a more efficient and leak-proof manner, connection pools such as HikariCP or Tomcat JDBC Pool are highly recommended. Deploy these pools in the /lib directory and be sure to put on your swimming trunks by setting them up correctly in the ServletContextListener's contextInitialized().

Deploy the ServletContextListener cavalry

Implement a ServletContextListener that wields the mighty power of manual deregistration in its contextDestroyed() method. This relentless soldier ensures things get cleaned up properly whenever your web application is undeployed:

public void contextDestroyed(ServletContextEvent sce) { Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); if (driver.getClass().getClassLoader() == getClass().getClassLoader()) { try { // JDBC driver, you are the weakest link, goodbye!👋 DriverManager.deregisterDriver(driver); } catch (SQLException e) { // Well that was unexpected... } } } }

Put JDBC Drivers in their place: Tomcat's /lib directory

This makes DriverManager believe the JDBC driver is associated with the system classloader rather than your specific webapp, reducing its chance of overstaying its welcome.

Keep your JDBC driver up-to-date

Like milk in your fridge, an outdated JDBC driver can result in something sour - so check for updates!

Handling Driver Deregistration

Manage shared drivers cautiously

Before you deregister a driver, remember others might be using it. Use the drivers.getClass().getClassLoader() check to consider shared drivers.

Connection pools need closing too

Before attempting to deregister the drivers, all good pool parties must come to an end. Close your connection pools, folks!

Try-catch to handle potential troublemakers

Handle SQLExceptions gracefully by employing try-catch blocks. Logs can tell great tales, perfect for helping with those debugging head-scratchers.

try { // Deregister logic. So long, and thanks for all the fish! } catch (SQLException e) { // Hey, we tried, didn't we? }

Nullify your data source references

Help out your garbage collector by setting data source references to null.