cstamas commented on code in PR #13588:
URL: https://github.com/apache/maven/pull/13588#discussion_r4308845784


##########
src/site/markdown/classloading.md:
##########
@@ -0,0 +1,372 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Maven Classloading
+
+This document describes the classloading mechanism used by Maven 4.x.
+Maven uses [Plexus Classworlds][classworlds] to build a hierarchy of isolated
+classloaders (called **realms**) so that plugins, extensions and the
+Maven core can each see only the classes they are supposed to see.
+
+The following diagram gives an overview of the realm hierarchy during a
+typical Maven build. Solid arrows indicate the parent classloader
+relationship. Dashed blue arrows indicate package imports. Dashed green
+arrows indicate export feeds.
+
+![Maven 4.x Classloader Hierarchy](images/classloading.svg)
+
+Each realm is described in detail below.
+
+## ClassWorlds Bootstrap ClassLoader
+
+This classloader is created and managed by the calling environment: the
+JVM launcher, an integration testing harness, or an IDE embedder.
+
+During a normal command-line invocation this is the JVM System
+ClassLoader and contains:
+
+- `${maven.home}/boot/plexus-classworlds-*.jar` — the Plexus
+  Classworlds library that bootstraps all other realms
+- Any `-javaagent` classes specified on the JVM command line
+
+## Maven Core Realm (`plexus.core`)
+
+Contains all Maven runtime classes: `MavenProject`, `AbstractMojo`,
+Plexus/Sisu DI, SLF4J, Guice, the Aether resolver, and more.
+
+The contents are configured by `${maven.home}/bin/m2.conf` and
+typically include:
+
+- `${maven.home}/lib/ext/*.jar`
+- `${maven.home}/lib/*.jar`
+
+This realm is the **container realm** in the Plexus/Sisu container
+unless core extensions are present, in which case the `maven.ext` realm
+takes over as the container realm (see below).
+
+## Core Extension Realms (`coreExtension>G:A:V`)
+
+Core extensions are loaded from `.mvn/extensions.xml` during Maven
+startup, **before the POM is parsed**. Each core extension gets its own
+isolated classloader. Because they load before POM parsing, core
+extensions can influence the build itself (e.g. polyglot Maven).
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extensions>
+  <extension>
+    <groupId>...</groupId>
+    <artifactId>...</artifactId>
+    <version>...</version>
+    <!-- optional: parent-first (default), self-first, plugin -->
+    <classLoadingStrategy>...</classLoadingStrategy>
+  </extension>
+</extensions>
+```
+
+Each extension can use `META-INF/maven/extension.xml` to declare
+exported packages and artifacts. These exports are aggregated into
+`CoreExports` and become visible to all plugins and build extensions
+through the Maven API realm.
+
+The `<classLoadingStrategy>` element controls the realm's parent
+wiring:
+
+| Strategy | Behavior |
+|---|---|
+| `parent-first` (default) | Imports everything from the core realm. Classes 
from the core are preferred over the extension's own. |
+| `plugin` | Imports only `CoreExports` packages (the Maven API surface). Same 
isolation as build extensions. |
+| `self-first` | Uses the core realm as parent but checks its own classes 
first. Allows the extension to override core classes. |
+
+Core extensions are loaded as part of Maven runtime startup and
+disposed of as part of Maven runtime shutdown.
+
+### Exports
+
+If a core extension includes `META-INF/maven/extension.xml`, it can
+declare which packages and artifacts it exports:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extension>
+  <exportedPackages>
+    <exportedPackage>org.example.myextension</exportedPackage>
+  </exportedPackages>
+  <exportedArtifacts>
+    <exportedArtifact>org.example:myextension</exportedArtifact>
+  </exportedArtifacts>
+</extension>
+```
+
+Exported packages become part of the Maven API surface — they are
+visible to all plugins and extensions. Exported artifacts are filtered
+from consumer classpaths to avoid class duplication.
+
+If no `extension.xml` is present, no packages or artifacts are exported,
+but the extension can still contribute components to Maven Core
+extension points (e.g. lifecycle mappings, event listeners) via Sisu
+component scanning.
+
+## Maven Extensions Realm (`maven.ext`)
+
+This realm is created only when core extensions are configured or when
+`-Dmaven.ext.class.path` is specified. It aggregates:
+
+- Exported packages from all core extension realms
+- JARs from `-Dmaven.ext.class.path` (added directly to the realm)
+
+If created, this realm becomes the container realm in the Plexus/Sisu
+container. If no core extensions or ext classpath entries exist,
+`plexus.core` remains the container realm.
+
+> **Known limitation:** JARs loaded via `-Dmaven.ext.class.path` are
+> added directly to the `maven.ext` realm, but their
+> `META-INF/maven/extension.xml` descriptors are never read. Declared
+> exports from these JARs are silently ignored. See
+> [MNG-8112](https://issues.apache.org/jira/browse/MNG-8112).
+
+## Maven API Realm (`maven.api`)
+
+This realm aggregates all exported packages from `CoreExports` — the
+union of Maven core exports and core extension exports. It does not
+contain any classes directly; it only imports from the container realm.
+
+This is the classloader that plugins and build extensions see as the
+"Maven API." It provides a clean, well-defined surface regardless of
+how Maven was launched.
+
+This realm has **no parent classloader** (`null`). It only contains
+what is explicitly imported from `CoreExports`. This ensures the
+Maven API classpath is consistent and does not include application or
+`-javaagent` classes.
+
+## Maven 4 API Realm (`maven.api.v4`)
+
+A more restricted view of the core, separate from `maven.api`, containing
+only:
+
+- `org.apache.maven.api` — the Maven 4 API surface
+- `org.slf4j` — logging
+
+Like `maven.api`, this realm has **no parent classloader** and imports
+directly from the container realm — it is not a child of `maven.api`.
+
+Maven 4 plugins (those using the new Maven 4 API) use this realm
+instead of `maven.api`. This ensures Maven 4 plugins only depend on
+the stable API, not on internal implementation classes.
+
+## Build Extension Realms (`extension>G:A:V`)
+
+Created for each `<build><extensions><extension>` declaration in the POM
+and for plugins with `<extensions>true</extensions>`. Both forms go
+through the same classloading path — the POM elements are converted into
+synthetic `Plugin` objects internally.
+
+Each build extension is loaded in a fully isolated classloader:
+
+- **Parent:** JVM System ClassLoader (provides access to `-javaagent`
+  classes)
+- **Imports:** all packages from `maven.api` (wildcard import)
+
+Build extensions can declare exports via
+`META-INF/maven/extension.xml`. These exports are imported into the
+project realm, making them visible to all plugins in that project.
+
+Maven guarantees that each distinct build extension (identified by
+plugin GAV and resolved dependencies) is loaded once and shared across
+all projects that use it. The `ExtensionRealmCache` manages this.
+
+Build extensions are **inherited from parent POMs**. The model merger
+combines parent and child extension lists, keyed by groupId:artifactId.
+
+## Project Realms (`project>G:A:V`)
+
+Project realms aggregate Maven API packages and packages exported by
+project build extensions.
+
+- **Parent:** `maven.api` realm
+- **Imports:** exported packages from each build extension realm
+
+Maven guarantees there is one project classloader per unique set of
+build extensions. Projects with identical extension sets share the same
+classloader.
+
+Legacy Maven 2.x build extensions (single-artifact extensions without
+`META-INF/maven/extension.xml`) are loaded directly into the project
+classloader rather than getting their own extension realm.
+
+## Plugin Realms (`plugin>G:A:V`)
+
+Each plugin gets its own isolated classloader:
+
+- **Parent:** JVM System ClassLoader (provides access to `-javaagent`
+  classes)
+- **Imports:** depends on whether the project has build extensions:
+  - **Without build extensions:** imports from `maven.api` directly
+  - **With build extensions:** imports from the project realm, which
+    gives access to both Maven API packages and build extension exports
+
+Maven creates one classloader per unique plugin + dependencies +
+build-extensions combination. The `PluginRealmCache` manages this.
+
+**Provided artifact filtering:** artifacts that are already in
+`CoreExports` are filtered from the plugin's classpath to avoid
+duplicate or conflicting classes. Maven 4 plugins (using `maven.api.v4`)
+get a tighter filter — only `org.apache.maven:maven-api-*` artifacts
+are filtered.
+
+## Exported Artifacts and Packages
+
+Maven Core, core extensions, and build extensions use
+`META-INF/maven/extension.xml` to declare their API surface:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extension>
+  <exportedPackages>
+    <exportedPackage>org.example.myextension</exportedPackage>
+  </exportedPackages>
+  <exportedArtifacts>
+    <exportedArtifact>org.example:myextension</exportedArtifact>
+  </exportedArtifacts>
+</extension>
+```
+
+**`exportedPackages`** are classname prefixes. Any class whose fully
+qualified name starts with one of these prefixes is importable by
+consumers. These prefixes are wired as foreign imports into the Maven
+API realm and from there into plugin and extension realms.
+
+**`exportedArtifacts`** are artifact coordinates in `groupId:artifactId`
+format. When Maven builds a plugin or extension classpath, artifacts
+matching these coordinates are excluded — they are already provided by
+the exporting realm, and including them would cause class duplication.
+
+## Component Visibility (Sisu Realm Scoping)
+
+Maven uses [Eclipse Sisu][sisu] for dependency injection. Sisu discovers
+components (JSR-330 `@Named` beans, Plexus `@Component` classes) by
+scanning each realm's classpath. Component **visibility** is scoped by
+the realm hierarchy: a component is only visible to consumers whose
+realm imports from the component's realm.
+
+This scoping is critical for build extensions that register
+project-specific components. For example, a build extension that
+registers a custom packaging type must only be visible to projects
+that declare that extension — not to other projects in the same reactor.
+
+### How Visibility Works
+
+Sisu's `FilteredBeans` mechanism filters component lookups based on
+the Thread Context ClassLoader (TCCL). When Maven processes a project,
+the TCCL is set to that project's realm. Lookups are filtered through
+the realm's import chain:
+
+| Component source | Visible to |
+|---|---|
+| Maven Core (container realm) | Everything |
+| Core extensions | Everything (exported into `CoreExports`) |
+| Build extensions | Only projects whose realm imports from the extension 
realm |
+| Plugins | Only within the plugin's own execution |
+
+### How It Is Wired
+
+When a core extension realm is created, `PlexusContainerCapsuleFactory`
+wires visibility in two directions:
+
+1. The extension realm imports from the container realm (`maven.ext`)

Review Comment:
   In Maven 3.9 it is opposite: maven.ext imports extension realm?



##########
src/site/markdown/classloading.md:
##########
@@ -0,0 +1,372 @@
+<!---
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Maven Classloading
+
+This document describes the classloading mechanism used by Maven 4.x.
+Maven uses [Plexus Classworlds][classworlds] to build a hierarchy of isolated
+classloaders (called **realms**) so that plugins, extensions and the
+Maven core can each see only the classes they are supposed to see.
+
+The following diagram gives an overview of the realm hierarchy during a
+typical Maven build. Solid arrows indicate the parent classloader
+relationship. Dashed blue arrows indicate package imports. Dashed green
+arrows indicate export feeds.
+
+![Maven 4.x Classloader Hierarchy](images/classloading.svg)
+
+Each realm is described in detail below.
+
+## ClassWorlds Bootstrap ClassLoader
+
+This classloader is created and managed by the calling environment: the
+JVM launcher, an integration testing harness, or an IDE embedder.
+
+During a normal command-line invocation this is the JVM System
+ClassLoader and contains:
+
+- `${maven.home}/boot/plexus-classworlds-*.jar` — the Plexus
+  Classworlds library that bootstraps all other realms
+- Any `-javaagent` classes specified on the JVM command line
+
+## Maven Core Realm (`plexus.core`)
+
+Contains all Maven runtime classes: `MavenProject`, `AbstractMojo`,
+Plexus/Sisu DI, SLF4J, Guice, the Aether resolver, and more.
+
+The contents are configured by `${maven.home}/bin/m2.conf` and
+typically include:
+
+- `${maven.home}/lib/ext/*.jar`
+- `${maven.home}/lib/*.jar`
+
+This realm is the **container realm** in the Plexus/Sisu container
+unless core extensions are present, in which case the `maven.ext` realm
+takes over as the container realm (see below).
+
+## Core Extension Realms (`coreExtension>G:A:V`)
+
+Core extensions are loaded from `.mvn/extensions.xml` during Maven
+startup, **before the POM is parsed**. Each core extension gets its own
+isolated classloader. Because they load before POM parsing, core
+extensions can influence the build itself (e.g. polyglot Maven).
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extensions>
+  <extension>
+    <groupId>...</groupId>
+    <artifactId>...</artifactId>
+    <version>...</version>
+    <!-- optional: parent-first (default), self-first, plugin -->
+    <classLoadingStrategy>...</classLoadingStrategy>
+  </extension>
+</extensions>
+```
+
+Each extension can use `META-INF/maven/extension.xml` to declare
+exported packages and artifacts. These exports are aggregated into
+`CoreExports` and become visible to all plugins and build extensions
+through the Maven API realm.
+
+The `<classLoadingStrategy>` element controls the realm's parent
+wiring:
+
+| Strategy | Behavior |
+|---|---|
+| `parent-first` (default) | Imports everything from the core realm. Classes 
from the core are preferred over the extension's own. |
+| `plugin` | Imports only `CoreExports` packages (the Maven API surface). Same 
isolation as build extensions. |
+| `self-first` | Uses the core realm as parent but checks its own classes 
first. Allows the extension to override core classes. |
+
+Core extensions are loaded as part of Maven runtime startup and
+disposed of as part of Maven runtime shutdown.
+
+### Exports
+
+If a core extension includes `META-INF/maven/extension.xml`, it can
+declare which packages and artifacts it exports:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extension>
+  <exportedPackages>
+    <exportedPackage>org.example.myextension</exportedPackage>
+  </exportedPackages>
+  <exportedArtifacts>
+    <exportedArtifact>org.example:myextension</exportedArtifact>
+  </exportedArtifacts>
+</extension>
+```
+
+Exported packages become part of the Maven API surface — they are
+visible to all plugins and extensions. Exported artifacts are filtered
+from consumer classpaths to avoid class duplication.
+
+If no `extension.xml` is present, no packages or artifacts are exported,
+but the extension can still contribute components to Maven Core
+extension points (e.g. lifecycle mappings, event listeners) via Sisu
+component scanning.
+
+## Maven Extensions Realm (`maven.ext`)
+
+This realm is created only when core extensions are configured or when
+`-Dmaven.ext.class.path` is specified. It aggregates:
+
+- Exported packages from all core extension realms
+- JARs from `-Dmaven.ext.class.path` (added directly to the realm)
+
+If created, this realm becomes the container realm in the Plexus/Sisu
+container. If no core extensions or ext classpath entries exist,
+`plexus.core` remains the container realm.
+
+> **Known limitation:** JARs loaded via `-Dmaven.ext.class.path` are
+> added directly to the `maven.ext` realm, but their
+> `META-INF/maven/extension.xml` descriptors are never read. Declared
+> exports from these JARs are silently ignored. See
+> [MNG-8112](https://issues.apache.org/jira/browse/MNG-8112).
+
+## Maven API Realm (`maven.api`)
+
+This realm aggregates all exported packages from `CoreExports` — the
+union of Maven core exports and core extension exports. It does not
+contain any classes directly; it only imports from the container realm.
+
+This is the classloader that plugins and build extensions see as the
+"Maven API." It provides a clean, well-defined surface regardless of
+how Maven was launched.
+
+This realm has **no parent classloader** (`null`). It only contains
+what is explicitly imported from `CoreExports`. This ensures the
+Maven API classpath is consistent and does not include application or
+`-javaagent` classes.
+
+## Maven 4 API Realm (`maven.api.v4`)
+
+A more restricted view of the core, separate from `maven.api`, containing
+only:
+
+- `org.apache.maven.api` — the Maven 4 API surface
+- `org.slf4j` — logging
+
+Like `maven.api`, this realm has **no parent classloader** and imports
+directly from the container realm — it is not a child of `maven.api`.
+
+Maven 4 plugins (those using the new Maven 4 API) use this realm
+instead of `maven.api`. This ensures Maven 4 plugins only depend on
+the stable API, not on internal implementation classes.
+
+## Build Extension Realms (`extension>G:A:V`)
+
+Created for each `<build><extensions><extension>` declaration in the POM
+and for plugins with `<extensions>true</extensions>`. Both forms go
+through the same classloading path — the POM elements are converted into
+synthetic `Plugin` objects internally.
+
+Each build extension is loaded in a fully isolated classloader:
+
+- **Parent:** JVM System ClassLoader (provides access to `-javaagent`
+  classes)
+- **Imports:** all packages from `maven.api` (wildcard import)
+
+Build extensions can declare exports via
+`META-INF/maven/extension.xml`. These exports are imported into the
+project realm, making them visible to all plugins in that project.
+
+Maven guarantees that each distinct build extension (identified by
+plugin GAV and resolved dependencies) is loaded once and shared across
+all projects that use it. The `ExtensionRealmCache` manages this.
+
+Build extensions are **inherited from parent POMs**. The model merger
+combines parent and child extension lists, keyed by groupId:artifactId.
+
+## Project Realms (`project>G:A:V`)
+
+Project realms aggregate Maven API packages and packages exported by
+project build extensions.
+
+- **Parent:** `maven.api` realm
+- **Imports:** exported packages from each build extension realm
+
+Maven guarantees there is one project classloader per unique set of
+build extensions. Projects with identical extension sets share the same
+classloader.
+
+Legacy Maven 2.x build extensions (single-artifact extensions without
+`META-INF/maven/extension.xml`) are loaded directly into the project
+classloader rather than getting their own extension realm.
+
+## Plugin Realms (`plugin>G:A:V`)
+
+Each plugin gets its own isolated classloader:
+
+- **Parent:** JVM System ClassLoader (provides access to `-javaagent`
+  classes)
+- **Imports:** depends on whether the project has build extensions:
+  - **Without build extensions:** imports from `maven.api` directly
+  - **With build extensions:** imports from the project realm, which
+    gives access to both Maven API packages and build extension exports
+
+Maven creates one classloader per unique plugin + dependencies +
+build-extensions combination. The `PluginRealmCache` manages this.
+
+**Provided artifact filtering:** artifacts that are already in
+`CoreExports` are filtered from the plugin's classpath to avoid
+duplicate or conflicting classes. Maven 4 plugins (using `maven.api.v4`)
+get a tighter filter — only `org.apache.maven:maven-api-*` artifacts
+are filtered.
+
+## Exported Artifacts and Packages
+
+Maven Core, core extensions, and build extensions use
+`META-INF/maven/extension.xml` to declare their API surface:
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<extension>
+  <exportedPackages>
+    <exportedPackage>org.example.myextension</exportedPackage>
+  </exportedPackages>
+  <exportedArtifacts>
+    <exportedArtifact>org.example:myextension</exportedArtifact>
+  </exportedArtifacts>
+</extension>
+```
+
+**`exportedPackages`** are classname prefixes. Any class whose fully
+qualified name starts with one of these prefixes is importable by
+consumers. These prefixes are wired as foreign imports into the Maven
+API realm and from there into plugin and extension realms.
+
+**`exportedArtifacts`** are artifact coordinates in `groupId:artifactId`
+format. When Maven builds a plugin or extension classpath, artifacts
+matching these coordinates are excluded — they are already provided by
+the exporting realm, and including them would cause class duplication.
+
+## Component Visibility (Sisu Realm Scoping)
+
+Maven uses [Eclipse Sisu][sisu] for dependency injection. Sisu discovers
+components (JSR-330 `@Named` beans, Plexus `@Component` classes) by
+scanning each realm's classpath. Component **visibility** is scoped by
+the realm hierarchy: a component is only visible to consumers whose
+realm imports from the component's realm.
+
+This scoping is critical for build extensions that register
+project-specific components. For example, a build extension that
+registers a custom packaging type must only be visible to projects
+that declare that extension — not to other projects in the same reactor.
+
+### How Visibility Works
+
+Sisu's `FilteredBeans` mechanism filters component lookups based on
+the Thread Context ClassLoader (TCCL). When Maven processes a project,
+the TCCL is set to that project's realm. Lookups are filtered through
+the realm's import chain:
+
+| Component source | Visible to |
+|---|---|
+| Maven Core (container realm) | Everything |
+| Core extensions | Everything (exported into `CoreExports`) |
+| Build extensions | Only projects whose realm imports from the extension 
realm |
+| Plugins | Only within the plugin's own execution |
+
+### How It Is Wired
+
+When a core extension realm is created, `PlexusContainerCapsuleFactory`
+wires visibility in two directions:
+
+1. The extension realm imports from the container realm (`maven.ext`)

Review Comment:
   In Maven 3.x it is opposite: maven.ext imports extension realm?



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