Extract a model from a Java repository
The Java extractor runs Spoon in noClasspath mode: it needs sources and
nothing else — no build, no jars, no classpath. This guide covers choosing the
source root, reading the resolution summary, and the one decision a multi-module
repository forces on you.
Before you start: a built codegraph-java.jar and a JDK on PATH
(see Install).
Extract one source root
-
Point
--srcat a source root — the directory the package hierarchy starts under, not the repository root.java -jar extractors/java/target/codegraph-java.jar \ --src fixtures/java/src --out acme.jsonlstdoutcarries only the roots and the model path, so it is safe to capture. The summary goes tostderr:RESOLUTION SUMMARY type references : 636 resolved : 601 unresolved : 35 resolution rate : 94.5% entities : 179 (stubs: 27) edges : 188 (self-edges dropped: 0)Progress is a bar on a terminal and silent when piped. Use
--progress plainfor a CI log (one line per phase, no control characters) or--no-progressfor neither. -
Check the model before you analyse it. The same check is the conformance gate every extractor must pass.
codegraph validate acme.jsonlchecked 1 model — 179 entities (27 stubs), 188 edges, lang java OK — every model conforms: closure, no self-reference, provenance, candidates, profile, anchors, ids.
Read the summary
resolution rateis the share of type references Spoon could resolve without a classpath. On the reference fixture it is 94.5%; the corpus is deliberately non-compilable, and the missing 5.5% are the three types it never declares plus Spoon’s<nulltype>.stubsare the degraded entities standing in for everything the corpus does not declare —java.lang.Stringas much as an absent vendor library. Their edges are kept, so the picture stays honest about its gaps. Membership is decided by a whitelist of corpus-declared types, never by a package-name prefix, becausenoClasspathinvents plausible fully-qualified names for types it cannot find.- A falling resolution rate between two runs of the same corpus means references stopped resolving — usually a source root that moved.
To see the model without stubs, pass --internal-only to any analysis command;
see Get a facts-only answer.
Decide how to handle a multi-module repository
--src is repeatable, and a repository whose modules share packages needs it to
be. The choice matters, so make it deliberately.
If the modules reference each other, then extract them in one run. Spoon resolves across every root it was given:
java -jar codegraph-java.jar --src modA --src modB --out both.jsonl resolution rate : 100.0%
entities : 11 (stubs: 2)The cross-module dependency comes out as a declared fact
(java:com.b -> java:com.a).
If you extract each module separately, then expect stubs and conflicts. Each run only knows its own root, so the other module’s types become stubs in it. The union still loads — every analysis command takes several models — but the same type is a class in one file and a stub in the other:
codegraph validate modA.jsonl modB.jsonl error duplicate-id/duplicate-id-conflict …
id "java:com.a/A" is declared 2 times and the declarations disagree on kind or traitsand the dependency degrades from -> (declared) to ~> (derived).
Separate models are the right answer only when the modules genuinely do not share packages — a Java service and a Kotlin one, or two products in one monorepo.
src/main/java and src/test/java of the same
module. The same package under two roots is what confuses noClasspath
resolution; extract main, and extract test as its own model if you need it.Record where the sources came from
If you want the city and the navigator to link back to a hosted repository, hand the extractor the facts — it runs no git itself:
java -jar codegraph-java.jar --src src/main/java --out gson.jsonl \
--repo-remote https://github.com/google/gson \
--repo-commit b3f4ca2 --repo-root gson/src/main/javacodegraph snapshots supplies these per frame on its own.