blob: 7215d24bf28e059ff295c88ff7dd9a7c83c0239a [file] [log] [blame]
------
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.