Why must a ProjectConnection be closed, and what is the idiomatic way to ensure that happens?
answer
- implements Closeable
- try-with-resources / Kotlin use
- close on exception too
- close() != stop daemon
- disconnect() for the connector
basics
~10 sProjectConnection implements Closeable and holds a connection to the Gradle daemon. If you do not close it you leak resources. Use try-with-resources so close() runs even on exceptions.
solid answer
~40 sA `ProjectConnection` is not just a handle — it holds live resources: the connection to a Gradle daemon and any associated buffers. If you never call `close()`, those resources stay open, daemons can be held longer than necessary, and in long-running tools (an IDE process) this leaks over time. Because `ProjectConnection extends Closeable`, the idiomatic pattern is Java **try-with-resources** (or Kotlin's `use { }`): the connection is closed automatically at the end of the block, including when an exception is thrown mid-build. Closing the connection does not kill the daemon — daemons are pooled and reused across connections — it just releases this connection's hold on it. You can additionally call `connector.disconnect()` to tear down a connector's resources, but per-connection cleanup via `close()` is the part you must never skip.
code
kotlin · 6 linesGradleConnector.newConnector()
.forProjectDirectory(projectDir)
.connect()
.use { connection ->
connection.newBuild().forTasks("build").run()
} // close() called automatically, even on failurego deeper
Know ProjectConnection is Closeable and you should close it, ideally with try-with-resources.
Explain it holds a daemon connection, and that close() runs on exceptions with try-with-resources / use.
Distinguish close() vs disconnect() vs stopping daemons; discuss leaks in long-running hosts.
Reason about resource governance in an IDE that opens hundreds of connections over a session.
## ProjectConnection is a resource `ProjectConnection` implements `java.io.Closeable`. It represents an active link to a Gradle **daemon** — the background JVM that runs builds. While the connection is open, it holds that link plus internal state. Leaking it is a real bug in long-lived hosts (an IDE that imports many projects over a session). ## try-with-resources / use Because it is `Closeable`, you get deterministic cleanup for free: ### Java ```java try (ProjectConnection connection = GradleConnector.newConnector() .forProjectDirectory(projectDir) .connect()) { connection.newBuild().forTasks("build").run(); } // close() runs here, even if run() threw ``` ### Kotlin ```kotlin GradleConnector.newConnector() .forProjectDirectory(projectDir) .connect() .use { connection -> connection.newBuild().forTasks("build").run() } ``` The key guarantee: `close()` is invoked whether the block completes normally **or** throws. Manual `try/finally` works too but is more error-prone. ## close() vs disconnect() vs stopping daemons - `ProjectConnection.close()` — releases **this connection**. Mandatory. - `GradleConnector.disconnect()` — releases resources associated with the **connector** itself (and connections created from it). Optional, useful when you are done with a connector entirely. - Neither necessarily **stops the daemon**. Daemons are pooled and reused for performance; they idle out (default ~3 hours) or can be stopped with `gradle --stop` from the CLI. The Tooling API intentionally keeps them alive so the next build is fast. ## Why this matters in interviews Forgetting `close()` is the single most common Tooling API mistake. Knowing that closing the connection is different from killing the daemon shows you understand the daemon-pooling model underneath.
- Does closing the ProjectConnection stop the Gradle daemon?No. Daemons are pooled and reused; close() only releases this connection. Daemons idle out or are stopped with gradle --stop.
- What is the difference between close() and the connector's disconnect()?close() releases a single ProjectConnection; disconnect() releases the connector and its connections when you are completely done with it.
saying these in an interview costs you the question
- Claiming close() kills the daemon
- Skipping close() and relying on GC / finalizers