# Understanding the Maven Execution Model: Lifecycles, Phases, and Execution Plans

> Master the Maven execution model. Learn how lifecycles, phases, and plugins create immutable execution plans for efficient builds. Understand the core of Maven's build automation.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: deep-dive
- Published: 2026-07-06

---

**The Maven execution model is a deterministic system that translates command-line goals into an immutable sequence of plugin executions (Mojos) by mapping lifecycles and phases through the `LifecycleExecutor` to create a `MavenExecutionPlan`.**

The Maven execution model forms the architectural backbone of Apache Maven, determining how build commands transform into concrete tool executions. In the `apache/maven` repository, this model is implemented primarily within the `org.apache.maven.lifecycle` package, where the core runtime orchestrates everything from lifecycle mapping to the final execution of build steps.

## Core Concepts of the Maven Execution Model

At its foundation, the model organizes build operations into three hierarchical concepts: **lifecycles**, **phases**, and **goals** (Mojos).

### Lifecycles and Phases

Maven defines a set of default **lifecycles**—specifically `default`, `clean`, and `site`—each representing an ordered list of **phases** such as `validate`, `compile`, `test`, and `package`. The mapping from phase names to their respective lifecycles, along with the complete ordered phase list for each lifecycle, is maintained in **`DefaultLifecycles`**. This class, located at [`impl/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycles.java), serves as the definitive registry for built-in build sequences.

### Goals and Mojos

While phases define the build sequence, **goals** represent the actual work performed. Each goal corresponds to a **Mojo** (Maven Plain Old Java Object), which is a specific task implemented by a plugin. The execution model binds these Mojos to phases, creating a concrete list of operations to perform.

## Building the Execution Plan

When you invoke a command like `mvn clean install`, Maven does not immediately execute plugins. Instead, it constructs an immutable **MavenExecutionPlan** through a multi-stage calculation process.

### Task Segmentation and Resolution

The entry point is the **`DefaultLifecycleExecutor`** ([`impl/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/DefaultLifecycleExecutor.java)), which implements the `LifecycleExecutor` interface. This component first uses a **`LifecycleTaskSegmentCalculator`** to divide the requested command-line tasks into discrete segments. It then invokes the **`LifecyclePluginResolver`** to resolve any missing plugin versions before the plan is calculated, ensuring all required build tools are identified and versioned.

### Calculating Mojo Executions

The core calculation logic resides in **`DefaultLifecycleExecutionPlanCalculator`** at [`impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java). This component performs three critical operations:

1. **`calculateMojoExecutions`** – Generates the ordered list of `MojoExecution` objects required for the requested tasks.
2. **`setupMojoExecutions`** (optional) – Enriches each `MojoExecution` with its plugin descriptor and configuration, resolving any late-bound parameters.
3. **Plan Assembly** – Wraps each `MojoExecution` in an immutable **`ExecutionPlanItem`** and assembles the final `MavenExecutionPlan`.

## The Immutable Execution Plan

The **`MavenExecutionPlan`** class ([`impl/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/MavenExecutionPlan.java)) represents the definitive, immutable blueprint for the build. Once constructed, this plan cannot be modified, guaranteeing reproducibility across build runs.

The plan maintains several key data structures:

- **`phasesInExecutionPlan`** – A pre-computed list of distinct phases in execution order.
- **`lastMojoExecutionForAllPhases`** – A mapping that allows Maven to quickly locate the final Mojo for any given phase, essential for incremental builds and reporting.
- **ExecutionPlanItem list** – An ordered collection where each item wraps a single `MojoExecution` along with its execution context.

Utility methods expose the list of `MojoExecution`s, identify non-thread-safe plugins, and provide phase-specific lookups.

## Execution Flow

After calculation, control flows back to **`DefaultLifecycleExecutor`**, which delegates to the **`LifecycleStarter`** to execute the immutable plan. The high-level flow follows this sequence:

1. The Maven CLI invokes `DefaultLifecycleExecutor.calculateExecutionPlan()`.
2. Task segments are calculated and plugin versions are resolved.
3. `DefaultLifecycleExecutionPlanCalculator` builds the `MavenExecutionPlan` containing `ExecutionPlanItem`s.
4. `LifecycleStarter.execute(session)` runs the plan against the current Maven session.

This separation between plan calculation and plan execution ensures that the build logic is validated and locked before any file system modifications occur.

## Programmatically Accessing the Execution Model

You can interact with the Maven execution model programmatically using the `LifecycleExecutor` interface. Below are practical examples for inspecting build plans.

### Printing the Execution Plan

This example demonstrates how to obtain and display the execution plan for a given set of tasks:

```java
import org.apache.maven.execution.MavenSession;
import org.apache.maven.lifecycle.LifecycleExecutor;
import org.apache.maven.lifecycle.MavenExecutionPlan;

public class PlanPrinter {
    private final LifecycleExecutor executor;

    public PlanPrinter(LifecycleExecutor executor) {
        this.executor = executor;
    }

    public void printPlan(MavenSession session, String... tasks) throws Exception {
        MavenExecutionPlan plan = executor.calculateExecutionPlan(session, tasks);
        System.out.println("Execution plan for tasks: " + String.join(" ", tasks));
        plan.getMojoExecutions().forEach(m -> 
            System.out.println("- " + m.getPlugin().getArtifactId() + ":" + m.getGoal() + " (" + m.getLifecyclePhase() + ")")
        );
    }
}

```

### Finding the Last Mojo in a Phase

You can leverage the plan's phase mapping to identify specific execution points:

```java
import org.apache.maven.lifecycle.MavenExecutionPlan;
import org.apache.maven.lifecycle.internal.ExecutionPlanItem;

MavenExecutionPlan plan = executor.calculateExecutionPlan(session, "install");
ExecutionPlanItem lastCompile = plan.findLastInPhase("compile");
if (lastCompile != null) {
    System.out.println("Last compile mojo: " + lastCompile.getMojoExecution().getGoal());
}

```

## Summary

- The **Maven execution model** organizes builds into lifecycles, phases, and goals, with definitions stored in `DefaultLifecycles`.
- **`DefaultLifecycleExecutionPlanCalculator`** transforms command-line requests into an immutable **`MavenExecutionPlan`** by resolving plugins and calculating `MojoExecution`s.
- The execution plan pre-computes phase ordering and mojo mappings, storing them in `ExecutionPlanItem` wrappers for efficient lookup.
- **`DefaultLifecycleExecutor`** serves as the façade, delegating plan construction to the calculator and execution to `LifecycleStarter`.
- The plan's immutability ensures build reproducibility once the calculation phase completes.

## Frequently Asked Questions

### What is the difference between a Maven phase and a goal?

A **phase** represents a stage in the build lifecycle (such as `compile` or `test`), defined as an ordered list within `DefaultLifecycles`. A **goal** represents a specific task performed by a plugin (a Mojo). When you run a phase, Maven executes all goals bound to that phase and all preceding phases in the lifecycle. Goals can also be invoked directly by name.

### How does Maven resolve plugin versions when building the execution plan?

During the plan calculation phase, `DefaultLifecycleExecutionPlanCalculator` invokes `LifecyclePluginResolver` to resolve any plugin versions not explicitly declared in the POM. This resolution occurs before `calculateMojoExecutions` is called, ensuring that every `MojoExecution` in the final plan has a concrete, resolved plugin version.

### Is the Maven execution plan mutable during the build?

No. The **`MavenExecutionPlan`** is immutable once constructed by the `LifecycleExecutionPlanCalculator`. It contains an ordered list of `ExecutionPlanItem` objects that cannot be modified after creation. This design guarantees that the build steps remain deterministic and reproducible throughout the execution phase managed by `LifecycleStarter`.

### What component actually runs the execution plan?

While `DefaultLifecycleExecutionPlanCalculator` builds the plan, the **`DefaultLifecycleExecutor`** delegates the actual execution to **`LifecycleStarter`**. The executor calculates the plan first, then passes the immutable `MavenExecutionPlan` to the starter, which iterates through the `ExecutionPlanItem`s and invokes each Mojo against the current `MavenSession`.