skip to content

Why must a ProjectConnection be closed, and what is the idiomatic way to ensure that happens?

level: middleimportance: must knowfreq 40%

answer

  1. implements Closeable
  2. try-with-resources / Kotlin use
  3. close on exception too
  4. close() != stop daemon
  5. disconnect() for the connector

basics

~10 s

ProjectConnection 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 s

A `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 lines
kotlin
GradleConnector.newConnector()
    .forProjectDirectory(projectDir)
    .connect()
    .use { connection ->
        connection.newBuild().forTasks("build").run()
    } // close() called automatically, even on failure

go deeper

for a junior

Know ProjectConnection is Closeable and you should close it, ideally with try-with-resources.

for a middle

Explain it holds a daemon connection, and that close() runs on exceptions with try-with-resources / use.

for a senior

Distinguish close() vs disconnect() vs stopping daemons; discuss leaks in long-running hosts.

for a principal

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

context