Skip to main content

ClassLoader Hierarchy & Metaspace Safety

In JVM applications that compile classes on the fly, careless classloading is the primary cause of Metaspace memory leaks (java.lang.OutOfMemoryError: Metaspace). A class can only be unloaded if and only if its defining ClassLoader is no longer reachable from any GC root.


ClassLoader Tree Structure​

Helix organizes dynamic ClassLoaders into a dedicated hierarchical model managed by ClassLoaderManager:

Bootstrap ClassLoader (JVM Runtime)AppClassLoader (Helix Application Classpath)SharedUtilityClassLoader (Common Helpers & Interfaces)RuleClassLoader: Finance / FraudRule_v1RuleClassLoader: Finance / FraudRule_v2RuleClassLoader: Retail / DiscountRule_v1Dynamic ChildDynamic Child (Hot Reload)Dynamic Child

Isolation Modes​

Helix supports 3 isolation modes configured via IsolationMode:

Isolation ModeArchitectureMetaspace CharacteristicsRecommended Use Case
ISOLATED1 unique RuleClassLoader per compiled rule.Maximum isolation. Discarding the rule ClassLoader instantly unloads the single class.Production multi-tenant services with dynamic rules.
HIERARCHICALNamespaced grouping (e.g. Finance, Retail). Rules in the same namespace share a parent loader.Balanced. Common utility classes are shared; tenant namespaces can be flushed together.Enterprise microservices with clear domain partitions.
SHARED_UTILITYCommon parent loader for shared helper functions; individual leaf loaders for rules.Minimizes class duplication across rules.High-volume single-tenant rule workloads.

Dynamic Class Unloading Lifecycle​

To safely evict and reclaim Metaspace when a rule is updated or deleted:

Avoiding Metaspace Leaks

Never store a direct reference to a dynamically loaded Class<?> or ClassLoader in a static field or long-lived ThreadLocal, as this will pin the ClassLoader and prevent HotSpot from reclaiming Metaspace.