| ------ |
| Guide to Maven Classloading |
| ------ |
| Jason van Zyl |
| Anders Kristian Andersen |
| ------ |
| 2008-12-10 |
| ------ |
| |
| ~~ 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. |
| |
| ~~ NOTE: For help with the syntax of this file, see: |
| ~~ http://maven.apache.org/doxia/references/apt-format.html |
| |
| Guide to Maven Classloading |
| |
| This is a description of the classloader hierarchy in Maven. |
| |
| * Overview |
| |
| * System Classloader |
| |
| * Core Classloader |
| |
| * Plugin Classloaders |
| |
| * Custom Classloaders |
| |
| [] |
| |
| |
| * 1. {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. |
| |
| An Ant script like this will show the contents of the system classloader: |
| |
| +---+ |
| <target name="info"> |
| <echo>java.class.path=${java.class.path}</echo> |
| </target> |
| +---+ |
| |
| |
| * 2. {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 |
| <<<{{{/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). |
| |
| |
| * 3. {Plugin Classloaders} |
| |
| 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. |
| |
| 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}}>>> |
| section of their project <<<pom.xml>>>. |
| Here is a sample of adding <<<ant-nodeps>>> to the plugin classloader of the Antrun Plugin and hereby enabling the use |
| of additional/optional Ant tasks: |
| |
| +---+ |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-antrun-plugin</artifactId> |
| <version>1.3</version> |
| <dependencies> |
| <dependency> |
| <groupId>org.apache.ant</groupId> |
| <artifactId>ant-nodeps</artifactId> |
| <version>1.7.1</version> |
| </dependency> |
| </dependencies> |
| ... |
| </plugin> |
| +---+ |
| |
| Plugins can inspect their effective runtime class path via the expressions <<<$\{plugin.artifacts\}>>> or |
| <<<$\{plugin.artifactMap\}>>> to have a list or map, respectively, of resolved artifacts injected from the |
| <<<{{{/ref/current/maven-plugin-api/apidocs/org/apache/maven/plugin/descriptor/PluginDescriptor.html}PluginDescriptor}}>>>. |
| |
| Please note that the plugin classloader does neither contain the |
| {{{/ref/current/maven-model/maven.html#class_dependency}dependencies}} |
| of the current project nor its build output. Instead, plugins can query the project's compile, runtime and test class path from the |
| <<<{{{/ref/current/apidocs/org/apache/maven/project/MavenProject.html}MavenProject}}>>> |
| in combination with the mojo annotation <<<requiresDependencyResolution>>> from the |
| {{{/developers/mojo-api-specification.html}Mojo API Specification}}. For instance, flagging a |
| mojo with <<<@requiresDependencyResolution runtime>>> enables it to query the runtime class path of the current project |
| from which it could create further classloaders. |
| |
| When a build plugin is executed, the thread's context classloader is set to the plugin classloader. |
| |
| |
| * 4. {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. |
| |
| It is important to understand that the plugin classloader cannot load classes from any of those custom classloaders. |
| Some factory patterns require that. Here you must add the classes to the plugin classloader as shown before. |