cmunier opened a new pull request, #1918:
URL: https://github.com/apache/maven-mvnd/pull/1918

   After each build, mvnd evicts the cached realms that refer to artifacts in 
the build tree, e.g. the realm of a Maven plugin built in the same reactor, and 
disposes them. These realms were never garbage collected: Sisu's JSR250 
`LifecycleManager` caches the lifecycle of every component class with strong 
`Class` keys and does not flush it when a realm is disposed 
(eclipse-sisu/sisu-project#281). So the daemon kept one more copy of such a 
plugin with every build, and metaspace grew until `mvnd --stop`.
   
   The new component `RealmDisposer` disposes the realm like before and then 
calls `LifecycleManager.flushCacheFor(clazz -> clazz.getClassLoader() == 
realm)`. Sisu added this method in 0.9.0.M3 for this purpose. 
`InvalidatingPluginRealmCache`, `InvalidatingExtensionRealmCache` and 
`InvalidatingPluginDescriptorCache` use it instead of calling `disposeRealm` 
themselves. The `LifecycleManager` is the private `delegate` of the injected 
`BeanManager` (`PlexusLifecycleManager`), so it is read via reflection. If that 
fails, only the flush is skipped. This is a workaround for the Sisu bug. With 
eclipse-sisu/sisu-project#282, Sisu flushes the cache itself when a realm is 
disposed, the flush here finds nothing, and `RealmDisposer` can be removed 
again. Sisu comes 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 the Sisu fix 
only reaches mvnd after a Sisu release, a Maven release that includes it, and a 
Maven update i
 n mvnd. For `mvnd-1.x` (Maven 3.9.x) that may not happen at all. If you prefer 
to wait for Sisu instead, the issue can stay open until then.
   
   Note: if a component with `@PreDestroy` from an evicted realm was never 
released, `dispose()` of the container no longer calls its `@PreDestroy` after 
the flush. Such a component keeps the realm reachable anyway, and the realm is 
no longer used once it is evicted.
   
   Verified:
   - New `RealmDisposerTest`: creates a child realm in a container with JSR250 
lifecycle, lets the `BeanManager` manage a class of that realm (as Sisu does 
for every bound component class), disposes the realm and checks that it is 
garbage collected. Fails without the flush.
   - `./mvnw verify -pl '!integration-tests,!dist'`, and `ModuleAndPluginTest`, 
`ExtensionsTest`, `ResidentExtensionsTest`, `SingleModuleTest`, 
`MultiModuleTest`, `StopStatusTest`.
   - Manually with the `module-and-plugin` test project: `mvnd clean install` 
four times in a fresh daemon, then `jcmd <pid> GC.run` and counting the loaded 
`HelloMojo` classes with `jcmd <pid> VM.class_hierarchy`: 1, 2, 3, 4 without 
this change; 0 after every build with it.
   
   If this is fine for you, I'll open the same change for `mvnd-1.x` 
(cherry-pick with one small conflict). It matters most there: `mvnd-1.x` embeds 
Maven 3.9.x, which may never get a Sisu version with the fix.
   
   Fixes #1917
   
   AI disclosure: drafted with Claude Code (Anthropic Claude Opus 5.5, 
interactive mode). I have reviewed and tested the change myself.
   
   ---
   
   - [x] I hereby declare this contribution to be licensed under the [Apache 
License Version 2.0, January 2004](https://www.apache.org/licenses/LICENSE-2.0)
   - [ ] I hereby declare that I have filed an [Apache Individual Contributor 
License Agreement](https://www.apache.org/licenses/icla.pdf).
   


-- 
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