You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kw...@apache.org on 2022/11/15 09:11:43 UTC

[maven-site] 01/01: [MNG-5771] Document all classloaders used in Maven

This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch feature/core-and-build-extensions
in repository https://gitbox.apache.org/repos/asf/maven-site.git

commit 7fbc8ecc56dee103a9a0498a694d319c8c59eb8b
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Nov 15 10:11:35 2022 +0100

    [MNG-5771] Document all classloaders used in Maven
    
    Clarify differences between Core and Build extensions
---
 .../apt/guides/mini/guide-maven-classloading.apt   | 84 +++++++++++++++-------
 content/apt/guides/mini/guide-using-extensions.apt | 13 ++--
 pom.xml                                            | 42 ++++++++++-
 src/plantuml/buildExtensionClassRealm.puml         | 46 ++++++++++++
 src/plantuml/pluginClassRealm.puml                 | 54 ++++++++++++++
 5 files changed, 208 insertions(+), 31 deletions(-)

diff --git a/content/apt/guides/mini/guide-maven-classloading.apt b/content/apt/guides/mini/guide-maven-classloading.apt
index 7215d24b..30416ad7 100644
--- a/content/apt/guides/mini/guide-maven-classloading.apt
+++ b/content/apt/guides/mini/guide-maven-classloading.apt
@@ -30,28 +30,35 @@
 Guide to Maven Classloading
 
  This is a description of the classloader hierarchy in Maven.
- 
+
+%{toc|section=1|fromDepth=2}
+
 * Overview
 
- * System Classloader
+ Maven uses the {{{https://codehaus-plexus.github.io/plexus-classworlds/}Plexus Classworlds}} classloading framework with which we
+ create our classloader graph. If you look in your <<<$\{maven.home\}/boot>>> directory you will see a single JAR
+ which is the Classworlds JAR we use to boot the classloader graph. The Classworlds JAR is the only element of
+ the Java <<<CLASSPATH>>> and Classworlds then builds the other classloaders or realms in Classworlds terminology.
  
- * Core Classloader
+ Each realm exposes
  
- * Plugin Classloaders
+ [[1]] optionally some classes imported from 0..n other classloaders
  
- * Custom Classloaders
-
- [] 
+ [[2]] optionally some classes from a directory or JAR
+ 
+ [[3]] one parent classloader
  
+ []
  
-* 1. {System Classloader}
+ The search order is always as given above.
 
- Maven uses the {{{https://codehaus-plexus.github.io/plexus-classworlds/}Plexus Classworlds}} classloading framework with which we
- create our classloader graph. If you look in your <<<$\{maven.home\}/boot>>> directory you will see a single JAR
- which is the Classworlds JAR we use to boot the classloader graph. The Classworlds JAR is the only element of
- the Java <<<CLASSPATH>>> and Classworlds then builds the other classloaders or realms in Classworlds terminology.
+* {Platform Classloader}
+
+ This is the classloader exposing all JRE classes.
+
+* {System Classloader}
  
- An Ant script like this will show the contents of the system classloader:
+ An Ant script like this will show the contents of the system/bootstrap classloader:
  
 +---+
     <target name="info">
@@ -59,26 +66,53 @@ Guide to Maven Classloading
     </target>
 +---+
 
+ It imports the platform classloader.
 
-* 2. {Core Classloader}
+* {Core Classloader}
  
- The second classloader down the graph contains the core requirements of Maven. More precisely, the core classloader
- has the libraries in <<<$\{maven.home\}/lib>>>. In general these are just Maven libraries, e.g. instances of
+ The second classloader down the graph contains the core requirements of Maven. <<It is only used by Maven internally but not by Plugins>>. 
+ The core classloader has the libraries in <<<$\{maven.home\}/lib>>>. In general these are just Maven libraries, e.g. instances of
  <<<{{{/ref/current/apidocs/org/apache/maven/project/MavenProject.html}MavenProject}}>>>
  belong to this classloader.
- We hope to further separate these in the future to just be Maven APIs and have 
- the implementations selected at runtime as required by the system.
  
  You can add elements to this classloader by {{{/ref/current/maven-model/maven.html#class_extension}extensions}}. 
  These are loaded into the same place as <<<$\{maven.home\}/lib>>> and hence are available 
- to the Maven core and all plugins for the current project and subsequent projects (in future, we
- plan to remove it from subsequent projects).
+ to the Maven core and all plugins for the current project (through the API classloader).
+ More information available in {{{./guide-using-extensions.html}Core Extension}}.
+
+* {API Classloader}
+
+ This exposes a filtered view of the Core Classloader by only exposing the exported packages from all Core Extensions.
+ The main API is listed in {{{https://maven.apache.org/ref/3-LATEST/maven-core/core-extensions.html}Maven Core Extensions Reference}}.
+ 
+ This has been introduced with Maven 3.3.1 ({{{https://issues.apache.org/jira/browse/MNG-5771}MNG-5771}}).
+
+* {Build Extension Classloaders}
 
-  
-* 3. {Plugin Classloaders}
+[../../buildExtensionClassRealm.svg] Build Extension Class Realm
 
- After that, each plugin has its own classloader that is a child of Maven's core classloader. 
- The classes in this classloader are taken from the dependencies in the plugin's dependency list.
+ For every plugin which is marked with <<<\<extensions\>true\</extensions\>>>> or a build extension listed in the according section of the POM there is
+ a dedicated classloader. Those are isolated (i.e. one build extension does not have access to other build extensions).
+ It imports everything from API classloader.
+ All JSR 330 or Plexus components declared in the underlying JAR are registered as components in the global Plexus container
+ while creating the classloader.
+ In addition all component references in the plugin descriptor are properly wired from the underlying Plexus container.
+ Build extensions have limited effect as they are loaded late.
+
+* {Project Classloaders}
+
+ There is one project classloader per Maven project (identified through its GAV).
+ This one imports the API Classloader. In addition it exposes all classes from all Build Extension Classloaders which are bound to the current project.
+ This is only released with the container.
+ During the build outside Mojo executions, the thread's context classloader is set to the project classloader.
+
+* {Plugin Classloaders}
+
+[../../pluginClassRealm.svg] Plugin Class Realm
+
+ Each plugin (which is not marked as build extension) has its own classloader that imports the Project classloader. 
+ 
+ Plugins marked with <<<\<extensions\>true\</extensions\>>>> leverage the Build Extension classloader instead of the Plugin classloader.
 
  Users can add dependencies to this classloader by adding dependencies 
  to a plugin in the <<<{{{/ref/current/maven-model/maven.html#class_plugin}plugins/plugin}}>>>
@@ -118,7 +152,7 @@ Guide to Maven Classloading
  When a build plugin is executed, the thread's context classloader is set to the plugin classloader.
 
 
-* 4. {Custom Classloaders}
+* {Custom Classloaders}
  
  Plugins are free to create further classloaders on their discretion. For example, a plugin might want to create a
  classloader that combines the plugin class path and the project class path.
diff --git a/content/apt/guides/mini/guide-using-extensions.apt b/content/apt/guides/mini/guide-using-extensions.apt
index 115fe5bc..76f87f14 100644
--- a/content/apt/guides/mini/guide-using-extensions.apt
+++ b/content/apt/guides/mini/guide-using-extensions.apt
@@ -28,7 +28,8 @@
 
 Using Extensions
 
- Extensions are a way to add classes to {{{./guide-maven-classloading.html#Core_Classloader}Core Classloader}}.
+ Extensions are a way to add classes to either the {{{./guide-maven-classloading.html#Core_Classloader}Core Classloader}} (Core Extensions) 
+ or the {{{./guide-maven-classloading.html#Project_Classloaders}Project Classloader}} (Build Extensions).
  This is necessary for adjusting Maven in a way that affects more than just one plug-in.
 
  The mechanism allows to either replace default {{{https://www.eclipse.org/sisu/}Sisu components}} with custom ones or add
@@ -40,10 +41,12 @@ Using Extensions
 
 * Loading Extensions
 
- There are different means of loading extensions. They can be distinguished into <<early>> and <<late>> loading behaviour. Some extensions require early loading.
- Please refer to the extension's documentation whether early loading is required.
+ There are different means of loading extensions depending on the type. There are <core extensions> which are loaded <<early>>
+ and build extensions which are loaded <<late>>.
+ Some extensions require early loading as they fundamentally change Maven behaviour.
+ Please refer to the extension's documentation whether they provide a core or a build extension.
 
-** Early Loading
+** Core Extension
 
   * Registered via extension jar in <<<$\{maven.home\}/lib/ext>>>
 
@@ -53,7 +56,7 @@ Using Extensions
 
   []
 
-** Late Loading
+** Build Extension
 
   * Registered via {{{../../pom.html#Plugins}<<<project->build->plugins->plugin>>>}} with element <<<extensions>>> being set to <<<true>>>. This is useful for regular plug-ins carrying some extensions.
   
diff --git a/pom.xml b/pom.xml
index a0147741..c743139b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,7 @@
     <doxiaVersion>2.0.0-M3</doxiaVersion>
     <doxiaToolsVersion>2.0.0-M3</doxiaToolsVersion>
     <javaVersion>8</javaVersion>
+    <siteDirectory>${project.basedir}/content</siteDirectory>
   </properties>
 
   <repositories>
@@ -111,7 +112,7 @@
           <artifactId>maven-site-plugin</artifactId>
           <version>4.0.0-M3</version>
           <configuration>
-            <siteDirectory>${project.basedir}/content</siteDirectory>
+            <siteDirectory>${siteDirectory}</siteDirectory>
             <skipDeploy>true</skipDeploy><!-- don't deploy site with maven-site-plugin -->
           </configuration>
           <dependencies>
@@ -283,6 +284,45 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>it.mulders.puml</groupId>
+        <artifactId>plantuml-maven-plugin</artifactId>
+        <version>0.1</version>
+        <dependencies>
+          <dependency>
+            <groupId>it.mulders.puml</groupId>
+            <artifactId>plantuml-v1-adapter</artifactId>
+            <version>0.2</version>
+          </dependency>
+          <dependency>
+            <groupId>net.sourceforge.plantuml</groupId>
+            <artifactId>plantuml</artifactId>
+            <version>1.2022.12</version>
+          </dependency>
+        </dependencies>
+        <executions>
+          <execution>
+            <id>generate-svg-from-plantuml</id>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+            <phase>pre-site</phase>
+            <configuration>
+              <sourceFiles>
+                <directory>src/plantuml</directory>
+                <includes>
+                  <include>**/*.dot</include>
+                  <include>**/*.puml</include>
+                </includes>
+              </sourceFiles>
+              <outputDirectory>${project.reporting.outputDirectory}</outputDirectory>
+              <format>SVG</format>
+              <stripPath>src/plantuml</stripPath>
+            </configuration>
+          </execution>
+        </executions>
+        
+      </plugin>
 
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
diff --git a/src/plantuml/buildExtensionClassRealm.puml b/src/plantuml/buildExtensionClassRealm.puml
new file mode 100644
index 00000000..0065a9f7
--- /dev/null
+++ b/src/plantuml/buildExtensionClassRealm.puml
@@ -0,0 +1,46 @@
+/*
+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.  
+*/
+@startuml
+!pragma layout smetana
+Platform o-- Bootstrap
+Bootstrap  "1" o-- "many" BuildExtension
+API "1" o-- "many" BuildExtension
+CoreExtension "many" o-- "1" API
+
+class Bootstrap {
+ Plexus Classworlds
+}
+
+class CoreExtension {
+ all packages defined in "/META-INF/maven/extension.xml"
+}
+
+class Platform {
+ all JRE classes
+}
+
+class BuildExtension {
+ dependencies
+ classes
+}
+
+note right of API : Just composition of all Core Extensions
+note right of Bootstrap : ${maven.home}/boot
+note right of BuildExtension : Per GAV of plugin loaded with <extensions>true</extensions> or build extension
+@enduml
\ No newline at end of file
diff --git a/src/plantuml/pluginClassRealm.puml b/src/plantuml/pluginClassRealm.puml
new file mode 100644
index 00000000..fef2c72a
--- /dev/null
+++ b/src/plantuml/pluginClassRealm.puml
@@ -0,0 +1,54 @@
+/*
+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.  
+*/
+@startuml
+!pragma layout smetana
+Platform o-- Bootstrap
+Bootstrap  "1" o-- "many" Plugin
+API "1" o-- "many" Project
+CoreExtension "many" o-- "1" API
+Project "1" --o "many" Plugin
+BuildExtension "many" o-- "1"Project 
+class Bootstrap {
+ Plexus Classworlds
+}
+
+class CoreExtension {
+ all packages defined in "/META-INF/maven/extension.xml"
+}
+
+class Platform {
+ all JRE classes
+}
+
+class BuildExtension {
+ dependencies
+ classes
+}
+
+class Plugin {
+ dependencies
+ classes
+}
+
+note right of Plugin : Per GAV of plugin
+note right of Project : One per Maven POM
+note right of API : Just composition of all Core Extensions
+note right of Bootstrap : ${maven.home}/boot
+note right of BuildExtension : Per GAV of plugin loaded with <extensions>true</extensions> or build extension
+@enduml
\ No newline at end of file