------ 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 2.0.6+. * Overview * System Classloader * Core Classloader * Plugin Classloaders * Custom Classloaders [] * 1. {System Classloader} Maven uses the {{{http://classworlds.codehaus.org}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 <<>> 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: --- java.class.path=${java.class.path} --- * 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 <<<{{{http://maven.apache.org/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 {{{http://maven.apache.org/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 <<<{{{http://maven.apache.org/ref/current/maven-model/maven.html#class_plugin}plugins/plugin}}>>> section of their project <<>>. Here is a sample of adding <<>> to the plugin classloader of the Antrun Plugin and hereby enabling the use of additional/optional Ant tasks: --- org.apache.maven.plugins maven-antrun-plugin 1.3 org.apache.ant ant-nodeps 1.7.1 ... --- 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 <<<{{{http://maven.apache.org/ref/current/maven-plugin-api/apidocs/org/apache/maven/plugin/descriptor/PluginDescriptor.html}PluginDescriptor}}>>>. Please note that the plugin classloader does neither contain the {{{http://maven.apache.org/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 <<<{{{http://maven.apache.org/ref/current/apidocs/org/apache/maven/project/MavenProject.html}MavenProject}}>>> in combination with the mojo annotation <<>> from the {{{http://maven.apache.org/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.