cmunier opened a new issue, #1917:
URL: https://github.com/apache/maven-mvnd/issues/1917

   ### Affected version
   
   1.0.6 (also `mvnd-1.x` and `master`)
   
   ### Bug description
   
   After every build, `InvalidatingRealmCacheEventSpy` evicts the cached plugin 
and extension realms that refer to artifacts in the build tree. The caches then 
dispose these realms (`ClassWorld.disposeRealm`). This is needed for Maven 
plugins built in the same reactor. However, the disposed realms are never 
garbage collected. So with every build, the daemon keeps one more copy of the 
classes of each such plugin, and metaspace grows until `mvnd --stop`.
   
   The cause is in Sisu: the JSR250 `LifecycleManager` (enabled by Maven via 
`setJSR250Lifecycle(true)`) caches a lifecycle for every component class in a 
map with strong `Class` keys. When a realm is disposed, this cache is not 
flushed (eclipse-sisu/sisu-project#281, fix proposed in 
eclipse-sisu/sisu-project#282). Heap dump of a daemon after 3 builds, path to 
GC roots excluding weak/soft references:
   
   ```
   org.codehaus.plexus.classworlds.realm.ClassRealm  
(plugin>…:<in-reactor-maven-plugin>:…, already disposed)
   |- <classloader> class <MojoClass>
   |  |- key java.util.concurrent.ConcurrentHashMap$Node
   |  |  |- table java.util.concurrent.ConcurrentHashMap
   |  |  |  |- lifecycles org.eclipse.sisu.bean.LifecycleManager
   |  |  |  |  |- delegate org.eclipse.sisu.plexus.PlexusLifecycleManager
   |  |  |  |  |  |- plexusBeanManager 
org.codehaus.plexus.DefaultPlexusContainer
   |  |  |  |  |  |  |- container org.apache.maven.cli.DaemonMavenCli
   |  |  |  |  |  |  |  |- cli org.mvndaemon.mvnd.daemon.Server
   ```
   
   #### Reproducer
   
   The integration test project 
`integration-tests/src/test/projects/module-and-plugin` (one plugin module, one 
module using it). Run `mvnd clean install` several times in a fresh daemon. 
After each build, run `jcmd <pid> GC.run` and count the loaded `HelloMojo` 
classes with `jcmd <pid> VM.class_hierarchy`:
   
   | Build | 1 | 2 | 3 | 4 |
   |---|---|---|---|---|
   | `mvnd-1.x` (Maven 3.9.16) | 1 | 2 | 3 | 4 |
   | `master` (Maven 4.0.0-rc-7) | 1 | 2 | 3 | 4 |
   
   #### Impact in a real build
   
   The impact grows with the size of the realms. In a build with about 300 
modules (Tycho, several in-reactor Maven plugins; one of them is used with 32 
different `<dependencies>` sets, so it gets 32 realms per build), metaspace 
grew by about 0.75 GB per full build:
   
   | Build in the same daemon | 1 | 2 | 3 | 4 | 5 | 6 |
   |---|---|---|---|---|---|---|
   | Metaspace used after full GC | 1.05 GB | 1.79 GB | 2.54 GB | 3.28 GB | 
4.02 GB | 4.76 GB |
   
   Partial builds that do not rebuild the in-reactor plugins reuse the cached 
realms and stay flat. With `-XX:MaxMetaspaceSize`, the `lowNonHeap` expiration 
can stop the daemon between builds, but a single build can also fail with 
`OutOfMemoryError: Metaspace` before that.
   
   In that build, plugins and extensions add more retention paths, which I 
reported separately: apache/maven#13794 (merged; `MavenSession` stored the 
current project in thread locals of pool threads), eclipse-tycho/tycho#6471 / 
#6472 and eclipse-tycho/tycho#6473 / #6474. The Sisu cache is the one that 
affects every in-reactor plugin, with or without such extensions.
   
   #### Proposed fix
   
   The real fix belongs in Sisu (eclipse-sisu/sisu-project#282). mvnd gets Sisu 
with the embedded Maven distribution (Sisu 1.1.0 on `master` with Maven 
4.0.0-rc-7, 1.0.0 on `mvnd-1.x` with Maven 3.9.16), so it will take a Sisu 
release, a Maven release and a Maven update in mvnd until the Sisu fix arrives; 
for Maven 3.9.x maybe never. As a workaround until then, mvnd can flush the 
cache itself when it evicts a realm: `LifecycleManager.flushCacheFor(clazz -> 
clazz.getClassLoader() == realm)`. This method exists in Sisu since 0.9.0.M3 
for this purpose. With this change, the counts above stay at 0 after every 
build. PR for `master`: <tbd>. I can port it to `mvnd-1.x`, if you agree.
   
   ---
   
   AI disclosure: the analysis and this issue text were prepared with the help 
of an AI assistant (Claude Code, Claude Opus 5.5, interactive). I have reviewed 
the content and verified the findings.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to