This is an automated email from the ASF dual-hosted git repository.
tuglu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new 77d258c011b minor: Upgrade to JDK 25 (#19304)
77d258c011b is described below
commit 77d258c011bbc0c9019bd8c9eaf49359051c9a3a
Author: jtuglu1 <[email protected]>
AuthorDate: Thu Apr 16 10:31:06 2026 -0700
minor: Upgrade to JDK 25 (#19304)
Switches compiler to JDK 21, supports JDK 25 for future release, and drops
support for JDK 17. Corresponding dev list thread:
https://lists.apache.org/thread/ovk7y4hkvn6fpk71trnbvmno22l6n1bx.
---
.github/workflows/ci.yml | 8 +++----
.github/workflows/codeql.yml | 2 +-
.github/workflows/cron-job-its.yml | 2 +-
.github/workflows/docker-tests.yml | 2 +-
.github/workflows/static-checks.yml | 2 +-
.github/workflows/worker.yml | 2 +-
distribution/docker/Dockerfile | 2 +-
docs/operations/java.md | 2 +-
extensions-contrib/redis-cache/pom.xml | 5 ++++
extensions-core/kinesis-indexing-service/pom.xml | 10 ++++++++
indexing-service/pom.xml | 5 ++++
.../indexing/overlord/setup/JavaScriptUtil.java | 2 +-
licenses.yaml | 2 +-
pom.xml | 18 ++++++++++-----
processing/pom.xml | 4 ++++
.../guava/ParallelMergeCombiningSequenceTest.java | 14 +++++++----
.../apache/druid/segment/IndexMergerTestBase.java | 27 +++++++++++++---------
.../org/apache/druid/curator/CuratorModule.java | 11 +++++++--
.../apache/druid/curator/CuratorModuleTest.java | 18 +++++++--------
services/pom.xml | 5 ++++
20 files changed, 97 insertions(+), 46 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9ceeeef3d79..81b032387c6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- jdk: [ "17", "21" ]
+ jdk: [ "21", "25" ]
pattern: [ "C*", "N*", "D*,H*,L*", "I*,A*,U*", "K*,E*,W*,Z*,Y*,X*",
"M*,P*,O*", "R*,B*,Q*,V*", "S*", "T*,F*,G*,J*" ]
uses: ./.github/workflows/worker.yml
with:
@@ -32,7 +32,7 @@ jobs:
artifact_prefix: "unit-test-reports-jdk${{ matrix.jdk }}"
jdk: ${{ matrix.jdk }}
key: "test-jdk${{ matrix.jdk }}-[${{ matrix.pattern }}]"
- execute: ${{ matrix.jdk == '21' || github.event_name == 'push' ||
contains(github.event.pull_request.labels.*.name, 'test-jdk17') }}
+ execute: ${{ matrix.jdk == '25' || github.event_name == 'push' ||
contains(github.event.pull_request.labels.*.name, 'test-jdk21') }}
validate-dist:
uses: ./.github/workflows/worker.yml
@@ -47,7 +47,7 @@ jobs:
if: ${{ success() && !contains( github.event.pull_request.labels.*.name,
'jacoco:skip') && github.event_name != 'push' }}
with:
script: .github/scripts/create-jacoco-coverage-report.sh
- artifacts_to_download: "unit-test-reports-jdk21*"
+ artifacts_to_download: "unit-test-reports-jdk25*"
key: "coverage-jacoco"
run-separated-tests:
@@ -67,4 +67,4 @@ jobs:
with:
script: .github/scripts/run_unit-tests ${{ matrix.args }}
-Dmaven.test.failure.ignore=true
key: ${{ matrix.name }}
- artifact_prefix: "unit-test-reports-jdk21"
+ artifact_prefix: "unit-test-reports-jdk25"
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index f8b4a5ea102..3fbbae12ba7 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -44,7 +44,7 @@ jobs:
- uses: actions/setup-java@v5
with:
distribution: 'zulu'
- java-version: '17'
+ java-version: '21'
cache: 'maven'
# Initializes the CodeQL tools for scanning.
diff --git a/.github/workflows/cron-job-its.yml
b/.github/workflows/cron-job-its.yml
index 82798605e0a..834691d4e6b 100644
--- a/.github/workflows/cron-job-its.yml
+++ b/.github/workflows/cron-job-its.yml
@@ -41,7 +41,7 @@ jobs:
- name: setup java
uses: actions/setup-java@v5
with:
- java-version: '17'
+ java-version: '21'
distribution: 'zulu'
cache: maven
diff --git a/.github/workflows/docker-tests.yml
b/.github/workflows/docker-tests.yml
index b959f0f536f..cd68b2b980d 100644
--- a/.github/workflows/docker-tests.yml
+++ b/.github/workflows/docker-tests.yml
@@ -44,7 +44,7 @@ jobs:
uses: actions/setup-java@v5
with:
distribution: 'zulu'
- java-version: 17
+ java-version: 21
cache: 'maven'
- name: Run Docker tests
id: run-it
diff --git a/.github/workflows/static-checks.yml
b/.github/workflows/static-checks.yml
index 611f80634a2..297448b30ff 100644
--- a/.github/workflows/static-checks.yml
+++ b/.github/workflows/static-checks.yml
@@ -35,7 +35,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- jdk: [ '17', '21' ]
+ jdk: [ '21', '25' ]
uses: ./.github/workflows/worker.yml
with:
script: .github/scripts/packaging-check.sh
diff --git a/.github/workflows/worker.yml b/.github/workflows/worker.yml
index eb18e219a23..404650171ea 100644
--- a/.github/workflows/worker.yml
+++ b/.github/workflows/worker.yml
@@ -21,7 +21,7 @@ on:
jdk:
required: false
type: string
- default: '21'
+ default: '25'
script:
required: true
type: string
diff --git a/distribution/docker/Dockerfile b/distribution/docker/Dockerfile
index 6b16ec2b94f..447f9664c03 100644
--- a/distribution/docker/Dockerfile
+++ b/distribution/docker/Dockerfile
@@ -17,7 +17,7 @@
# under the License.
#
-ARG JDK_VERSION=17
+ARG JDK_VERSION=21
# The platform is explicitly specified as x64 to build the Druid distribution.
# This is because it's not able to build the distribution on arm64 due to
dependency problem of web-console. See:
https://github.com/apache/druid/issues/13012
diff --git a/docs/operations/java.md b/docs/operations/java.md
index a035e4e239c..f4a8c029db2 100644
--- a/docs/operations/java.md
+++ b/docs/operations/java.md
@@ -27,7 +27,7 @@ a Java runtime for Druid.
## Selecting a Java runtime
-Druid officially supports Java 17 and 21.
+Druid officially supports Java 21 and 25.
The project team recommends using an OpenJDK-based Java distribution. There
are many free and actively-supported
distributions available, including
diff --git a/extensions-contrib/redis-cache/pom.xml
b/extensions-contrib/redis-cache/pom.xml
index aaac3282b96..6bdbb5c8426 100644
--- a/extensions-contrib/redis-cache/pom.xml
+++ b/extensions-contrib/redis-cache/pom.xml
@@ -50,6 +50,11 @@
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ <version>2.12.1</version>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
diff --git a/extensions-core/kinesis-indexing-service/pom.xml
b/extensions-core/kinesis-indexing-service/pom.xml
index 0ce89c05cf8..fc47aaede6a 100644
--- a/extensions-core/kinesis-indexing-service/pom.xml
+++ b/extensions-core/kinesis-indexing-service/pom.xml
@@ -72,6 +72,16 @@
<artifactId>regions</artifactId>
<version>${aws.sdk.v2.version}</version>
</dependency>
+ <dependency>
+ <groupId>software.amazon.awssdk</groupId>
+ <artifactId>aws-core</artifactId>
+ <version>${aws.sdk.v2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
diff --git a/indexing-service/pom.xml b/indexing-service/pom.xml
index 0c676219f33..42e11720364 100644
--- a/indexing-service/pom.xml
+++ b/indexing-service/pom.xml
@@ -278,6 +278,11 @@
<version>2.48.0</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mozilla</groupId>
+ <artifactId>rhino-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git
a/indexing-service/src/main/java/org/apache/druid/indexing/overlord/setup/JavaScriptUtil.java
b/indexing-service/src/main/java/org/apache/druid/indexing/overlord/setup/JavaScriptUtil.java
index 1b969647fc8..84733010b28 100644
---
a/indexing-service/src/main/java/org/apache/druid/indexing/overlord/setup/JavaScriptUtil.java
+++
b/indexing-service/src/main/java/org/apache/druid/indexing/overlord/setup/JavaScriptUtil.java
@@ -31,7 +31,7 @@ public class JavaScriptUtil
{
public static <T> T compileSelectorFunction(Class<T> interfaceClass, String
function)
{
- final ScriptEngine engine = new
ScriptEngineManager().getEngineByName("js");
+ final ScriptEngine engine = new
ScriptEngineManager().getEngineByName("javascript");
Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
bindings.put("polyglot.js.nashorn-compat", true);
try {
diff --git a/licenses.yaml b/licenses.yaml
index 618d830d833..ec5c1762cd8 100644
--- a/licenses.yaml
+++ b/licenses.yaml
@@ -4042,7 +4042,7 @@ name: Rhino
license_category: binary
module: java-core
license_name: Mozilla Public License Version 2.0
-version: 1.7.14.1
+version: 1.8.0
copyright: Mozilla and individual contributors.
license_file_path: licenses/bin/rhino.MPL2
libraries:
diff --git a/pom.xml b/pom.xml
index dbcf3b21112..2059252685f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,7 +70,7 @@
</scm>
<properties>
- <java.version>17</java.version>
+ <java.version>21</java.version>
<maven.compiler.release>${java.version}</maven.compiler.release>
<project.build.resourceEncoding>UTF-8</project.build.resourceEncoding>
<aether.version>0.9.0.M2</aether.version>
@@ -683,7 +683,12 @@
<dependency>
<groupId>org.mozilla</groupId>
<artifactId>rhino</artifactId>
- <version>1.7.14.1</version>
+ <version>1.8.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mozilla</groupId>
+ <artifactId>rhino-engine</artifactId>
+ <version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
@@ -1740,7 +1745,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
- <version>3.26.0</version>
+ <version>3.28.0</version>
<configuration>
<linkXRef>false</linkXRef> <!-- prevent "Unable to locate
Source XRef to link to" warning -->
<printFailingErrors>true</printFailingErrors>
@@ -1765,7 +1770,7 @@
<plugin>
<groupId>de.thetaphi</groupId>
<artifactId>forbiddenapis</artifactId>
- <version>3.5.1</version>
+ <version>3.9</version>
<configuration>
<ignoreSignaturesOfMissingClasses>true</ignoreSignaturesOfMissingClasses>
<bundledSignatures>
@@ -2079,7 +2084,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
- <version>3.3.0</version>
+ <version>3.8.1</version>
<configuration>
<ignoredNonTestScopedDependencies>
<ignoredNonTestScopedDependency>*</ignoredNonTestScopedDependency>
@@ -2161,7 +2166,8 @@
<profile>
<id>java-12+</id>
<activation>
- <jdk>[12,)</jdk>
+ <!-- Security Manager was permanently removed in JDK 24 (JEP
486); this flag is fatal on 24+ -->
+ <jdk>[12,24)</jdk>
</activation>
<properties>
<jdk.security.manager.allow.argLine>
diff --git a/processing/pom.xml b/processing/pom.xml
index b184aabee03..37e2a420081 100644
--- a/processing/pom.xml
+++ b/processing/pom.xml
@@ -208,6 +208,10 @@
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport</artifactId>
+ </dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
diff --git
a/processing/src/test/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequenceTest.java
b/processing/src/test/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequenceTest.java
index d088e7e1afd..6e3881a5292 100644
---
a/processing/src/test/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequenceTest.java
+++
b/processing/src/test/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequenceTest.java
@@ -542,11 +542,15 @@ public class ParallelMergeCombiningSequenceTest
"You can increase query timeout or tune the
performance of query.", t.getMessage());
- // these tests when run in java 11, 17 and maybe others in between 8 and
20 don't seem to correctly clean up the
- // pool, however this behavior is flaky and doesn't always happen so we
can't definitively assert that the pool is
- // or isn't
- if (JvmUtils.majorVersion() >= 20 || JvmUtils.majorVersion() < 9) {
- Assert.assertTrue(pool.awaitQuiescence(3, TimeUnit.SECONDS));
+ // JDK 11-19: pool may not clean up reliably after a timeout (flaky), so
we skip the assertion.
+ // JDK 20-24: ForkJoinPool.managedBlock counts sleeping workers as
inactive, so isQuiescent()
+ // returns true once all ForkJoin tasks complete even if
managed-blocking workers are
+ // still sleeping — pool appears quiescent quickly after the
timeout exception.
+ // JDK 25+: post-JEP 491 changes count managed-blocking workers as active
while sleeping, so
+ // isQuiescent() correctly returns false until the blocked
worker wakes up and exits —
+ // the assertion would time out for long-sleeping sequences.
+ if (JvmUtils.majorVersion() >= 20 && JvmUtils.majorVersion() < 25) {
+ Assert.assertTrue(pool.awaitQuiescence(10, TimeUnit.SECONDS));
// good result, we want the pool to always be idle if an exception
occurred during processing
Assert.assertTrue(pool.isQuiescent());
}
diff --git
a/processing/src/test/java/org/apache/druid/segment/IndexMergerTestBase.java
b/processing/src/test/java/org/apache/druid/segment/IndexMergerTestBase.java
index ffe22d38b14..56ec53fe52c 100644
--- a/processing/src/test/java/org/apache/druid/segment/IndexMergerTestBase.java
+++ b/processing/src/test/java/org/apache/druid/segment/IndexMergerTestBase.java
@@ -86,6 +86,7 @@ import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -720,17 +721,21 @@ public abstract class IndexMergerTestBase extends
InitializedNullHandlingTest
}
// CompressedVSizeColumnarIntsSupplier$CompressedByteSizeColumnarInts
//
CompressedVSizeColumnarMultiIntsSupplier$CompressedVSizeColumnarMultiInts
- Field compressedSupplierField = obj.getClass().getDeclaredField("this$0");
- compressedSupplierField.setAccessible(true);
-
- Object supplier = compressedSupplierField.get(obj);
-
- Field compressionField =
supplier.getClass().getDeclaredField("compression");
- compressionField.setAccessible(true);
-
- Object strategy = compressionField.get(supplier);
-
- Assert.assertEquals(expectedStrategy, strategy);
+ // JDK 25+ restricts access to synthetic this$0 fields; traverse the
hierarchy for getCompressionStrategy() instead.
+ Class<?> cls = obj.getClass();
+ while (cls != null) {
+ try {
+ Method method = cls.getDeclaredMethod("getCompressionStrategy");
+ method.setAccessible(true);
+ Object strategy = method.invoke(obj);
+ Assert.assertEquals(expectedStrategy, strategy);
+ return;
+ }
+ catch (NoSuchMethodException e) {
+ cls = cls.getSuperclass();
+ }
+ }
+ Assert.fail("Could not find getCompressionStrategy() on " +
obj.getClass());
}
diff --git a/server/src/main/java/org/apache/druid/curator/CuratorModule.java
b/server/src/main/java/org/apache/druid/curator/CuratorModule.java
index d439966d8ac..95b4195e6f8 100644
--- a/server/src/main/java/org/apache/druid/curator/CuratorModule.java
+++ b/server/src/main/java/org/apache/druid/curator/CuratorModule.java
@@ -54,10 +54,11 @@ public class CuratorModule implements Module
static final int MAX_SLEEP_TIME_MS = 45000;
private final boolean haltOnFailedStart;
+ private final Runnable exitAction;
public CuratorModule()
{
- this(true);
+ this(true, () -> System.exit(1));
}
/**
@@ -65,8 +66,14 @@ public class CuratorModule implements Module
* due to unhandled curator exceptions.
*/
public CuratorModule(boolean haltOnFailedStart)
+ {
+ this(haltOnFailedStart, () -> System.exit(1));
+ }
+
+ CuratorModule(boolean haltOnFailedStart, Runnable exitAction)
{
this.haltOnFailedStart = haltOnFailedStart;
+ this.exitAction = exitAction;
}
@Override
@@ -214,7 +221,7 @@ public class CuratorModule implements Module
log.error(t, "Exception when stopping server after unhandled Curator
error.");
}
finally {
- System.exit(1);
+ exitAction.run();
}
}
diff --git
a/server/src/test/java/org/apache/druid/curator/CuratorModuleTest.java
b/server/src/test/java/org/apache/druid/curator/CuratorModuleTest.java
index 46257efc055..8708bbae25d 100644
--- a/server/src/test/java/org/apache/druid/curator/CuratorModuleTest.java
+++ b/server/src/test/java/org/apache/druid/curator/CuratorModuleTest.java
@@ -39,19 +39,17 @@ import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import java.util.List;
import java.util.Properties;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public final class CuratorModuleTest
{
private static final String CURATOR_CONNECTION_TIMEOUT_MS_KEY =
CuratorConfig.CONFIG_PREFIX + "." + CuratorConfig.CONNECTION_TIMEOUT_MS;
- @Rule
- public final ExpectedSystemExit exit = ExpectedSystemExit.none();
-
@Rule
public final LoggerCaptureRule logger = new
LoggerCaptureRule(CuratorModule.class);
@@ -74,12 +72,12 @@ public final class CuratorModuleTest
@Test(timeout = 60_000L)
public void exitsJvmWhenMaxRetriesExceeded() throws Exception
{
+ CountDownLatch exitCalled = new CountDownLatch(1);
Properties props = new Properties();
props.setProperty(CURATOR_CONNECTION_TIMEOUT_MS_KEY, "0");
- Injector injector = newInjector(props);
+ Injector injector = newInjector(props, exitCalled::countDown);
logger.clearLogEvents();
- exit.expectSystemExitWithStatus(1);
// This will result in a curator unhandled error since the connection
timeout is 0 and retries are disabled
CuratorFramework curatorFramework = createCuratorFramework(injector, 0);
@@ -100,6 +98,8 @@ public final class CuratorModuleTest
.equals("Unhandled error in Curator,
stopping server.")
)
);
+
+ Assert.assertTrue("System.exit was not called within timeout",
exitCalled.await(10, TimeUnit.SECONDS));
}
@Ignore("Verifies changes in https://github.com/apache/druid/pull/8458, but
overkill for regular testing")
@@ -109,7 +109,7 @@ public final class CuratorModuleTest
Properties props = new Properties();
String deprecatedPropName = CuratorConfig.CONFIG_PREFIX +
".terminateDruidProcessOnConnectFail";
props.setProperty(deprecatedPropName, "true");
- Injector injector = newInjector(props);
+ Injector injector = newInjector(props, () -> {});
try {
injector.getInstance(CuratorFramework.class);
@@ -119,12 +119,12 @@ public final class CuratorModuleTest
}
}
- private Injector newInjector(final Properties props)
+ private Injector newInjector(final Properties props, final Runnable
exitAction)
{
return new StartupInjectorBuilder()
.add(
new LifecycleModule(),
- new CuratorModule(false),
+ new CuratorModule(false, exitAction),
binder ->
binder.bind(ServiceEmitter.class).to(NoopServiceEmitter.class),
binder -> binder.bind(Properties.class).toInstance(props)
)
diff --git a/services/pom.xml b/services/pom.xml
index 03c15a9ad6d..0a4bf33581a 100644
--- a/services/pom.xml
+++ b/services/pom.xml
@@ -343,6 +343,11 @@
<artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mozilla</groupId>
+ <artifactId>rhino-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers-nginx</artifactId>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]