Why does noIsolation use the buildscript classpath, and what risk does that create when your worker action depends on a library Gradle also ships?
answer
- noIsolation = buildscript classloader, no custom classpath
- inherits Gradle's transitive versions
- NoSuchMethodError / silent drift on clashes
- fix: classLoaderIsolation + explicit classpath
- fine only when no version sensitivity
basics
~20 snoIsolation runs the action on the plugin/buildscript classloader, so you cannot pick a custom classpath. If your action needs a different version of a library Gradle bundles, you get the version Gradle exposes — leading to conflicts or wrong behavior.
solid answer
~50 s`noIsolation()` is the fastest mode precisely because it skips classpath setup: the `WorkAction` runs in the Gradle daemon JVM on the **same classloader your plugin was loaded with** (the buildscript classpath). That means whatever versions Gradle and your plugin expose are what the action sees — you can't override them. The classic pitfall: your action needs library X v2, but the daemon's classpath already has X v1 (perhaps Gradle's own dependency). Under noIsolation there's no way to inject v2; you'll bind against v1 and hit `NoSuchMethodError`, behavioral drift, or outright conflicts. The fix is to step up to `classLoaderIsolation` (or `processIsolation`) and set an explicit `classpath` containing exactly the versions your action needs — these modes load your classes in a separate classloader, decoupled from Gradle's. So noIsolation is great for light work with no version sensitivity, and wrong the moment you need classpath control.
code
kotlin · 7 lines// Problematic: action needs renderer 2.5 but daemon has 1.x
workerExecutor.noIsolation() // no classpath knob -> binds against 1.x
// Fixed:
workerExecutor.classLoaderIsolation {
classpath.from(configurations["renderTool"]) // pins 2.5 in its own loader
}go deeper
Know noIsolation uses the existing plugin classpath and you can't change it.
Explain the version-clash symptoms and that the remedy is classLoaderIsolation with an explicit classpath.
Articulate why this is a classloader-leakage problem and how a dedicated configuration pins versions cleanly.
Set a plugin convention that any worker depending on third-party libraries declares an isolated classpath rather than relying on the buildscript classloader.
## Why noIsolation has no custom classpath Isolation costs come mostly from constructing classloaders and forking JVMs. `noIsolation` skips both: the `WorkAction` executes in the **Gradle daemon JVM** using the **buildscript/plugin classloader** that already loaded your plugin. There is no `ClassLoaderWorkerSpec`, hence no `classpath` to set — you inherit exactly what's already loaded. ## The version-clash trap Gradle and its plugins bring their own transitive dependencies onto the buildscript classpath. If your worker action needs a *specific* (often newer or older) version of a library that is already present, noIsolation gives you the version on the classpath — not yours. Symptoms: - `NoSuchMethodError` / `NoClassDefFoundError` at runtime when the resolved version lacks an API you compiled against. - Silent behavioral differences when an older/newer version behaves differently. - Hard-to-debug conflicts because nothing in your build file declared the offending version — it leaked in transitively. ## The fix: step up a mode Both `classLoaderIsolation` and `processIsolation` expose a `classpath` (`ConfigurableFileCollection`). Populate it from a dedicated configuration holding exactly the versions your action requires; Gradle loads your action under a classloader built from that classpath, isolated from Gradle's own: ```kotlin val toolCp = configurations.create("renderTool") dependencies { add("renderTool", "com.example:renderer:2.5.0") } workerExecutor.classLoaderIsolation { classpath.from(toolCp) // pins renderer 2.5.0, immune to daemon's version } ``` ## When noIsolation is still right If your action only touches JDK classes and classes already provided by your plugin (and you're happy with those versions), noIsolation is the correct, fastest choice — there's nothing to isolate. The pitfall only bites when you need *control* over the classpath. Recognizing that boundary is the skill: "does my action care about a specific library version?" If yes, don't use noIsolation.
- Can you add a dependency to noIsolation work some other way, e.g. via parameters?No. Parameters pass data (Properties), not classes. Loading a different library version requires a separate classloader, which only classLoaderIsolation or processIsolation provide via their classpath.
- If noIsolation inherits the plugin classloader, why is it still faster?Because it constructs no new classloader and forks no process — the action just runs on classes already loaded in the daemon, so there is essentially zero setup overhead per submission.
saying these in an interview costs you the question
- Claiming you can set a custom classpath under noIsolation.
- Trying to fix a version clash by passing the jar through work parameters instead of switching isolation modes.