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]

Reply via email to