DEV Community

Victor Osório
Victor Osório

Posted on

3 2

Java Memory Leak for JDBC

The Context

I had written an engine using a custom ClassLoader. To do that just create a new URLClassLoader, load a jar and execute what code you want, than close the URLClassLoader. If the new ClassLoader doesn't have access to the current ClassLoader, the loaded classes does not have access to your code. Good! Very Good!

URL[] jars = new URL[] { /* The jars to be loaded */ }; //
try (URLClassLoader classLoader = new URLClassLoader(jars)) {
    Job job = classLoader.loadClass(Job.class.getName());
    job.execute();
}

The Problem

But... We do not have control with the code loaded from an external Jar. That is the problem. So if you want to avoid memory leaks the your custom classloader should be released by Garbage Collector. If the loaded code uses JDBC you will soon get an OutOfMemoryError and everything will crash! Not good!

The reason

Whe JDBC loads the driver they assumes that you will use only one ClassLoader, so it create a reference to your ClassLoader. This reference prevents the Garbage Collector from removing your custom ClassLoader from the memory.

So, even if you create your ClassLoader, execute your code and close it. The total of loaded classes will never decrease.

How to solve?

To solve this problem we have to unregister all JDBC drivers just after the execution, than close URLClassLoader.

URL[] jars = new URL[] { /* The jars to be loaded */ }; //
try (URLClassLoader classLoader = new URLClassLoader(jars)) {
  Job job = classLoader.loadClass(Job.class.getName());
  job.execute();
  Collections.list(DriverManager.getDrivers()).forEach(driver -> {
    try {
      DriverManager.deregisterDriver(driver);
    } catch (SQLException e) {
      logger.error("Error unregistering driver!", e);
    }
  });
} 

Now, let's look for the loaded classes:

Possible problems

  1. If the executed code create any Thread, the URLClassLoader is not eligible for Garbage Collector.
  2. If some library create any Thread, same problem from #1.
  3. MongoDb client create a Thread. 😫

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

AWS GenAI Live!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️