How Eclipse's Java Nature and Builder Drive Incremental Compilation
Eclipse compiles only what changed because the Java nature and javabuilder in .project subscribe to resource changes. Here's the minimal config, how to verify it, and when you still need Project > Clean.
10 Nov 2025, 11:13 UTC

If your Eclipse workspace recompiles only what changed instead of rebuilding everything on each save, that behavior comes from two lines in the project's .project file: the Java nature org.eclipse.jdt.core.javanature and the builder org.eclipse.jdt.core.javabuilder. Understanding this pairing explains why errors appear live in the Problems view, why a Project > Clean sometimes fixes phantom errors, and why committing .metadata to git is a mistake.
The mechanism: natures enable tooling, builders do the work
Eclipse models a project as a set of resources plus metadata. A nature is a tag that tells Eclipse which tooling applies to a project. A builder is a component registered to receive resource change events (file saved, file added, folder deleted) and react to them. The Java Development Tools (JDT) pair one nature with one builder:
org.eclipse.jdt.core.javanaturemarks the project as Java, enabling JDT views, refactoring, and classpath resolution.org.eclipse.jdt.core.javabuildersubscribes to workspace change notifications and incrementally compiles affected compilation units plus their dependents.
"Incremental" means the builder keeps dependency state from previous builds (stored under the workspace's .metadata directory) and recompiles only the changed files and anything that depends on them. That is the engineering decision that keeps a workspace with hundreds of thousands of lines responsive: a save triggers a targeted compile, not a full one.
A minimal working configuration
A hand-created or repaired Java project needs two files at the project root. First, .project:
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>demo-app</name>
<comment></comment>
<projects></projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments></arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>Second, .classpath, which tells the builder where sources live and where class files go:
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path="bin"/>
</classpath>With these in place and Project > Build Automatically enabled, saving a .java file triggers the builder, and compile errors appear in the Problems view within a moment. No manual build invocation is needed.
Verifying it works
Three quick checks confirm the setup rather than assuming it:
- Open
.projectand confirm both the nature and builder IDs above are present. A missing builder means no compilation happens at all; a missing nature means JDT features silently don't apply. - With Build Automatically on, introduce a deliberate syntax error in a source file and save. The error should appear in the Problems view without any build action.
- Check that
bin/(or your configured output folder) receives fresh.classfiles after a save.
Limits: when incremental state drifts
The builder reacts to Eclipse resource change events. Changes made outside Eclipse — editing a file in another editor, a git checkout or merge, restoring files from backup — can bypass or race those listeners, leaving the incremental index inconsistent with the disk. The symptom is stale errors on code that is now correct, or missing errors on broken code. The remedy is Project > Clean, which discards build outputs and forces a full recompile of the selected projects.
Other real limits:
- Annotation processors and generated sources are only picked up if configured (via project properties or a build tool integration). A processor run by Maven but unknown to JDT produces classes Eclipse can't see.
- Builder ordering matters. If you add a custom builder (for code generation, say) after
javabuilderinbuildSpec, the Java compile runs before its inputs exist. Custom builders belong before the Java builder. - Builders run on the workspace build thread. A heavy custom builder or a workspace with many projects can make auto-build noticeably slow and block UI operations that need the workspace lock.
Common mistakes
- Committing
.metadatato version control. It holds machine-specific incremental state and absolute paths. Commit.projectand.classpath; ignore.metadataand output folders. - Disabling Build Automatically and expecting live errors. With auto-build off, the Problems view only updates on manual builds — a frequent source of "Eclipse didn't catch this" confusion.
- Mixing Maven/Gradle natures with a hand-edited
.classpath. When them2eor Buildship nature is present, the build tool owns the classpath. Manual edits get overwritten or, worse, coexist and cause duplicate compilation and conflicting entries. Pick one source of truth. - Assuming identical behavior across Eclipse releases or non-Java natures. PDE, PyDev, and others implement their own builders with different incremental semantics.
When to reach for Clean
Clean is a state-changing operation — it deletes build outputs and rebuilds — so use it deliberately: after external edits or merges, after switching branches with large diffs, or when error markers clearly disagree with the source on disk. If errors persist after a Clean, the problem is real configuration (classpath, missing generated sources), not stale state, and further Cleans won't help.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.