Groovy 4 GroovyClassLoader cache change: dynamic scripts still grow heap in long-running JVM
0 reputation · 15 Aug 2026, 20:14 UTC
Groovy 4.0 documents that repeated dynamic compilation through fresh GroovyShell or GroovyClassLoader instances accumulates compiled classes in a static cache, which can leak memory in long-running JVM processes. The documented guidance is to reuse a single shared class loader or call GroovyClassLoader.clearCache() after use.
My goal is to run a service that compiles and executes user-supplied scripts continuously (thousands of compilations per day) without unbounded heap growth, while still isolating each script's classes so that recompiling a changed script picks up the new version. The uncertainty is how the cache interacts with loader reuse: a shared loader avoids the static-cache growth, but redefining the same script name appears to require either unique class names or a fresh loader, which reintroduces the original problem.
Environment assumption: Groovy 4.x on a modern HotSpot JVM, scripts compiled via GroovyShell.parse. I plan to verify by looping compilations and watching heap with and without clearCache().
Questions:
- With a shared
GroovyClassLoader, what is the supported way to recompile a script whose source changed without stale class reuse? - Does
clearCache()fully release compiled classes if the application still holds references to previously loaded script instances? - Is there a documented per-loader cache boundary in Groovy 4, or is the cache strictly static/global?