gnodet opened a new issue, #13223: URL: https://github.com/apache/maven/issues/13223
## Overview This issue tracks the overall plan for addressing Maven's classloading architecture problems. The full design document is at: https://gist.github.com/gnodet/fef0571deb83280f1df60e7cce1307a1 ## Problem Statement Maven's classloading architecture has several distinct but related problems: 1. **Global-only exports** — `META-INF/maven/extension.xml` `exportedPackages`/`exportedArtifacts` are injected into *all* plugin/extension realms via `CoreExports`. No per-consumer scoping. 2. **No import control for plugins/extensions** — plugins are passive recipients of whatever core globally exported. No way to say "I need package X in *my* realm only" (see #8997 / MNG-7921, MNG-7955). 3. **`maven.ext.class.path` gap** — entries on that system property bypass `extension.xml` discovery; their exports are silently ignored (see #10506 / MNG-8112, PR #13101 — currently targeting the wrong class). 4. **JPMS vs. unnamed module world** — PR #11029's `META-INF/maven/module-access` only helps named JPMS modules. The vast majority of plugins live in the unnamed module world and have no equivalent. 5. **Classworlds not owned** — `plexus-classworlds` is an external dependency Maven cannot evolve. ## Solution Layers ### Layer 0 — Own the classloading stack (prerequisite) Finish PR #11029: internalize `plexus-classworlds` as `impl/maven-classworlds` + `api/maven-api-classworlds`. All subsequent layers depend on Maven owning these types. ### Layer 1 — Per-realm import descriptor Extend `META-INF/maven/extension.xml` with import and strategy declarations so plugins/extensions can declare what they need imported into **their own realm only**: ```xml <extension> <!-- EXISTING: what this artifact exports to ALL other realms --> <exportedPackages>...</exportedPackages> <exportedArtifacts>...</exportedArtifacts> <!-- NEW: what this plugin/extension needs imported into ITS OWN realm only --> <importedPackages> <importedPackage>org.slf4j</importedPackage> <importedPackage>com.google.inject</importedPackage> </importedPackages> <importedArtifacts> <importedArtifact>com.google.inject:guice</importedArtifact> </importedArtifacts> <!-- NEW: classloader loading strategy --> <classLoaderStrategy>self-first</classLoaderStrategy> </extension> ``` Key design decisions: - `importedPackages`/`importedArtifacts` restricted to packages already in `CoreExports` — plugins cannot reach core internals - Descriptor read from primary artifact JAR only (not transitives) — avoids resolution chicken-and-egg - `classLoaderStrategy` in `extension.xml` is the artifact-level default; `.mvn/extensions.xml` `<classLoadingStrategy>` remains the project-level override Solves #8997 (MNG-7921) and MNG-7955. ### Layer 2 — Non-JPMS module access control Extend the same descriptor with module access for plugins in the unnamed module world: ```xml <extension> ... <moduleAccess> <!-- targeted at this realm's classloader only, not ALL-UNNAMED --> <addOpens>java.base/sun.nio.ch</addOpens> <addExports>jdk.internal.misc/jdk.internal.misc</addExports> </moduleAccess> </extension> ``` Subsumes and unifies PR #11029's `META-INF/maven/module-access` into a single descriptor. ### Layer 3 — Fix `maven.ext.class.path` (replaces PR #13101) In `PlexusContainerCapsuleFactory` (`o.a.maven.cling.invoker`, `impl/maven-cli` — **not** `MavenCli` in deprecated `compat/maven-embedder`): discover `extension.xml` from `maven.ext.class.path` entries, deduplicate by canonical path, include exports in `CoreExports`. ## Component Map | Component | Change | |---|---| | `api/maven-api-classworlds` | New module: public ClassWorld/ClassRealm/Strategy API (Layer 0 / #11029) | | `impl/maven-classworlds` | New module: inlined classworlds implementation (Layer 0 / #11029) | | `impl/maven-core` `ExtensionDescriptor` | Add: importedPackages, importedArtifacts, classLoaderStrategy, moduleAddOpens, moduleAddExports | | `impl/maven-core` `ExtensionDescriptorBuilder` | Add: parsing of the five new elements | | `impl/maven-core` `DefaultClassRealmManager` | Apply per-realm descriptor: targeted imports, module access, strategy | | `impl/maven-cli` `PlexusContainerCapsuleFactory` | Fix maven.ext.class.path discovery with path dedup | | `compat/maven-embedder` | **No new logic** — deprecated | ## Sequencing 1. **Layer 0** — finish #11029 (classworlds internalization) 2. **Layer 3** — rework #13101 targeting `impl/maven-cli` only 3. **Layer 1** — descriptor import/strategy extension, core of the feature 4. **Layer 2** — module access, follows layer 1, same descriptor format ## Related issues / PRs - #11029 — Internalize plexus-classworlds (Layer 0) - #13101 — Honor export descriptors from extension classpath (Layer 3, needs rework) - #8997 — Allow plugins to control classpath extensions (MNG-7921, addressed by Layer 1) - #10506 — MNG-8112 (addressed by Layer 3) - MNG-7955 — Plugins should be allowed some control over imported packages (addressed by Layer 1) -- 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]
