Skip to content

Commit a8ce88f

Browse files
Pin the Java toolchain to JDK 21 using java { toolchain {…} } (#4366)
* Use `toolchain { languageVersion = … }` to reliably pin the Java toolchain to JDK 21. This decouples the build from whatever JDK the developer happens to have on `PATH`. * Disable auto-provisioning of JDKs. Gradle will pick a matching JDK from its detected local JDK installations. * Drop the manual `JavaVersion.current().isCompatibleWith(VERSION_17)` guard. It is no longer necessary because the toolchain already ensures an appropriate JDK will be used. * Apply `options.release = 17` to **every** `JavaCompile` task. Previously it was only `compileJava`, so tests were actually targeting Java 21. * In `PendingWritesQueueConcurrencyTest`, remove an inadvertent dependency on the JDK 19 API (namely, a try-with-resources statement taking advantage of `ExecutorService` being auto-closeable) in order to make it compile under `--release 17`. Apart from pinning the JDK cleanly, toolchains also interact better with the Build Cache. Gradle folds the toolchain JDK identity into the build cache key, so cached compile outputs are tied to the JDK that produced them rather than just to `javac` arguments.
1 parent 02fa096 commit a8ce88f

3 files changed

Lines changed: 32 additions & 25 deletions

File tree

build.gradle

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ subprojects {
197197
apply from: rootProject.file('gradle/testing.gradle')
198198

199199
java {
200+
toolchain {
201+
languageVersion = JavaLanguageVersion.of(21)
202+
}
203+
204+
// Pin `sourceCompatibility`/`targetCompatibility` to match the bytecode and API target that we set for
205+
// `JavaCompile` tasks via `options.release` below. This also makes IntelliJ’s Gradle importer set the
206+
// appropriate `languageLevel` in `.idea/misc.xml`.
200207
sourceCompatibility = JavaVersion.VERSION_17
201208
targetCompatibility = JavaVersion.VERSION_17
202209
}
@@ -256,14 +263,16 @@ subprojects {
256263
linksOffline "https://foundationdb.github.io/fdb-record-layer/api/fdb-record-layer-core/", "${packageListDir}/fdb-record-layer-core/"
257264
}
258265
}
259-
compileJava {
260-
//enable compilation in a separate daemon process
266+
267+
// Override some options on every compile task (main and test).
268+
tasks.withType(JavaCompile).configureEach {
269+
// Enable compilation in a separate daemon process.
261270
options.fork = true
262271

263-
//enable incremental compilation
272+
// Enable incremental compilation.
264273
options.incremental = true
265274

266-
//target byte-code compatibility with Java 17 (regardless of build JDK)
275+
// Compile against the Java 17 API and emit Java 17 bytecode.
267276
options.release = 17
268277
}
269278
}
@@ -356,10 +365,6 @@ clean {
356365

357366
apply from: 'gradle/sphinx.gradle'
358367

359-
if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) {
360-
throw new Exception("Java 17 is required to build fdb-record-layer")
361-
}
362-
363368
// fdb-environment.properties is the old way we configured the library path and cluster file, it does not scale well
364369
// to multiple cluster files, so is being replaced with a yaml file.
365370
def fdbEnvironmentFile = new File("${rootProject.projectDir}/fdb-environment.properties")

fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/queue/PendingWritesQueueConcurrencyTest.java

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -90,24 +90,23 @@ void testRandomizedConcurrentEnqueueAndScan(long seed) throws Exception {
9090
// list append, so commit order and list order agree.
9191
final Object commitLock = new Object();
9292

93-
try (ExecutorService executor = Executors.newFixedThreadPool(WORKER_COUNT)) {
94-
List<Future<?>> futures = new ArrayList<>(WORKER_COUNT);
95-
try {
96-
for (int worker = 0; worker < WORKER_COUNT; worker++) {
97-
final int workerId = worker;
98-
// Per-worker Random seeded deterministically from the global seed + workerId
99-
futures.add(executor.submit(() -> {
100-
workerLoop(queue, workerId, new Random(seed + workerId), recorded, drained, commitLock);
101-
return null;
102-
}));
103-
}
104-
for (Future<?> future : futures) {
105-
future.get(120, TimeUnit.SECONDS);
106-
}
107-
} finally {
108-
executor.shutdownNow();
109-
assertTrue(executor.awaitTermination(30, TimeUnit.SECONDS), "executor did not shut down");
93+
final ExecutorService executor = Executors.newFixedThreadPool(WORKER_COUNT);
94+
List<Future<?>> futures = new ArrayList<>(WORKER_COUNT);
95+
try {
96+
for (int worker = 0; worker < WORKER_COUNT; worker++) {
97+
final int workerId = worker;
98+
// Per-worker Random seeded deterministically from the global seed + workerId
99+
futures.add(executor.submit(() -> {
100+
workerLoop(queue, workerId, new Random(seed + workerId), recorded, drained, commitLock);
101+
return null;
102+
}));
103+
}
104+
for (Future<?> future : futures) {
105+
future.get(120, TimeUnit.SECONDS);
110106
}
107+
} finally {
108+
executor.shutdownNow();
109+
assertTrue(executor.awaitTermination(30, TimeUnit.SECONDS), "executor did not shut down");
111110
}
112111

113112
// Drain whatever the workers left behind, in a single consistent snapshot, recording

gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ apiVersion=710
3636
mavenLocalEnabled=false
3737
org.gradle.daemon=true
3838

39+
# Don’t try to auto-provision JDKs. We prefer to only resolve Java toolchains from locally installed JDKs.
40+
org.gradle.java.installations.auto-download=false
41+
3942
url = 'https://github.com/FoundationDB/fdb-record-layer/'
4043

4144
# Control which places we attempt to publish to

0 commit comments

Comments
 (0)