Explain Codes LogoExplain Codes Logo

Unloading classes in java?

java
class-loading
garbage-collection
class-unloading
Anton ShumikhinbyAnton Shumikhin·Mar 9, 2025
TLDR

Unload Java classes by nullifying references to a custom ClassLoader and its loaded classes, thus marking them for garbage collection:

class MyClassLoader extends ClassLoader { // Time to take out the trash } MyClassLoader loader = new MyClassLoader(); Class<?> myClass = loader.loadClass("MyClass"); // Do some stuff with the class... // Ready for the big sleep myClass = null; loader = null; // Dropping hints to the GC System.gc();

Key: Class unloading effectively happens via custom ClassLoader isolation. Note that System.gc() is a suggestion to the JVM, not a command.

Deep dive into class unloading

The relationship between class unloading and the garbage collector (GC) is akin to a dance coordinated around the lifecycle of the ClassLoader. When ClassLoader instances are garbage collected, any classes they loaded become eligible for GC, if no more references exist.

Harnessing the power of multiple classloaders

Consider employing multiple Classloaders for diverse portions of your application:

  1. Individual JARs for each module of your app.
  2. Assign each JAR a unique JarClassLoader.
  3. MultiClassLoader manages different class versions per connection or peer.

OSGi: The heavyweight champion

For large-scale applications teeming with complex dependencies, it's worth looking into OSGi:

  1. Efficient and powerful dependency management.
  2. Robust component lifecycle control.
  3. Enhanced updates and version management capabilities.

The art of classloader strategy

Deploy proxy Classloaders and invent custom class loading strategies to master the class lifecycle:

  1. Determine class loading sequence to mitigate conflicts.
  2. Keep class and classloader associations in HashMaps for ease of management.
  3. Supervise classloader hierarchy to boost stability with a proxy classloader.

Design considerations

  1. A correct hierarchy to keep ClassCastException and LinkageError at bay.
  2. Delegate responsibility wisely to prevent system ClassLoader bottleneck.
  3. Plan for quick class reloading, negating the need for JVM restarts.

The lifecycle of your not-so-average classloader

ClassLoader Lifecycle: 1. Birth (🌱) 2. Load'em up, partner! (📦🆙) 3. The end (of the world as we know it) (⌛) ==> Brings forth GC 🚚 unloading classes (♻️📤)

Forcing the hand of class unloading

Rare occasions call for forced class unloading without the gruesome task of killing off the JVM. This peculiar feat can be accomplished:

  1. By playing 'dead': drop all references to the class and its faithful ClassLoader.
  2. By nudging the garbage collector using System.gc(), albeit it's more of a polite hint than an imperious command.

Dancing to different class versions

In the wild world of server farms, the MultiClassLoader strategy comes to the rescue:

  1. Juggling several versions of a single class in the air simultaneously, because who doesn't love a good challenge?
  2. Dividing the load (and unload) cycles into separate baskets, based on server connections (one per MultiClassLoader).

It's not you, it's me: dropping references for GC

For a class to bow out gracefully, it's essential to:

  1. Sever all static and instance bonds.
  2. Ensure threads aren't running around executing methods of the class like headless chickens.
  3. See to it proxies, caches, pools take a step back, accepting the end of class instances.