What it is

Computed, not declared.

maddi is a whole-program static analyzer for Java — and for Kotlin, through a shared syntax tree. You don’t write annotations: maddi computes them. It reads your sources and your classpath, follows how objects flow between fields, parameters and return values, and derives @Immutable, @Container, @Modified and @Independent for every type, method and field.

You write

public class Range {
    private final int lo;
    private final int hi;
}

maddi computes

@Immutable
@Container
public class Range {
    private final int lo;
    private final int hi;
}

Nothing in your source has to change. maddi derives the annotations — and where you do write them yourself, it checks them against what it computed.

How it reports

How far each type got.

Real code is rarely deeply immutable, and a yes/no answer throws away everything useful. maddi reports how far a type got, and what stopped it going further.

How far did it get?

Every type lands on one of four levels. Which one it reaches tells you how far you got — and the reason it stopped there is exactly what you would have to change to go further.

Honest about hidden content

hc=true records the one catch: a link runs to the elements of a type parameter maddi cannot see into. It is not hc-free @Immutable, and the analyzer does not pretend otherwise.

Eventual immutability

@Mark, @Only and @Immutable(after=…) describe the builder and freeze patterns: types that are mutable while being constructed, and immutable ever after.

In your own code

Use the annotations without adopting the analyzer.

The one thing your own code compiles against is the annotations library. It is on Maven Central, targets Java 17, and is Apache-2.0 — so you can depend on it without taking on the analyzer’s LGPL.

Gradle

implementation("io.codelaser:maddi-annotation:0.9.1")

Maven

<dependency>
  <groupId>io.codelaser</groupId>
  <artifactId>maddi-annotation</artifactId>
  <version>0.9.1</version>
</dependency>

That gives you @Immutable, @Container, @Independent, @Modified and friends, with no dependencies at all — useful as documentation and as contracts on your interfaces even before you run the analyzer, since maddi verifies them against what it computes.

If you also want the eventually-final support classes — SetOnce, Freezable, EventuallyFinal, Lazy and FirstThen — depend on io.codelaser:maddi-support instead. It declares exactly one dependency, on maddi-annotation, and re-exports it. Versions up to 0.8.2 were LGPL-3.0; 0.9.0 onward is Apache-2.0.

Where it stands

Status — August 2026

0.9.1 is the first release where every part is installable: the Gradle plugin on the Plugin Portal, the Maven plugin and the annotations on Maven Central, and self-contained command-line distributions on GitHub Releases.

PartState
Concepts, and the bookStable
Parser / resolver (javac front end)Solid; run against many open-source projects and one closed-source 3M-line codebase
Modification & immutability analysisSettles on the same verified answer every time, on all our test projects — Timefold, LangChain4j, Fernflower, Guava, ActiveMQ, Jenkins, Camel
Gradle / Maven pluginsPublished in 0.9.1; both tested against a set of real multi-module builds
Kotlin front endWorks; ships only via the maddi-kotlin command-line download

The analyzer is stable on everything we run it on — and your codebase will contain Java that ours do not. If maddi mis-reads your code, crashes, or works something out you can argue is wrong, that is exactly the report we want: please open an issue.

Where it came from

From e2immu to maddi.

maddi re-implements e2immu, which ran from 2020 until it was archived. Same ideas, rewritten analyzer, now covering Java and Kotlin. The root Java package was org.e2immu.*, after its predecessor; it became io.codelaser.maddi.* in 0.9.1.

maddi is developed by Bart Naudts at CodeLaser, and is and will remain open source. The analyzer is LGPL-3.0; the annotations — the only artifacts your own code compiles against — are Apache-2.0 from 0.9.0 onward. CodeLaser’s commercial engine is built on this analyzer; the analyzer stays here, under this licence.

© 2026 CodeLaser · maddi is LGPL-3.0 · annotations Apache-2.0