diff --git a/.github/actions/integration-test-setup/action.yml b/.github/actions/integration-test-setup/action.yml index 1a4a1521830..e955d583080 100644 --- a/.github/actions/integration-test-setup/action.yml +++ b/.github/actions/integration-test-setup/action.yml @@ -9,7 +9,7 @@ inputs: jdk-version: description: JDK version required: false - default: "21" + default: "25" runs: using: composite diff --git a/.github/actions/java-setup/action.yml b/.github/actions/java-setup/action.yml index 8f7f43e3c04..65331989826 100644 --- a/.github/actions/java-setup/action.yml +++ b/.github/actions/java-setup/action.yml @@ -9,14 +9,14 @@ inputs: java-version: description: The Java version that is going to be set up. required: false - default: "21" + default: "25" runs: using: composite steps: - id: setup-java name: Setup Java - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: ${{ inputs.distribution }} java-version: ${{ inputs.java-version }} diff --git a/.github/scripts/ansible/roles/keycloak_remote_installer/README.md b/.github/scripts/ansible/roles/keycloak_remote_installer/README.md index 2083135bb63..b66b88cd84b 100644 --- a/.github/scripts/ansible/roles/keycloak_remote_installer/README.md +++ b/.github/scripts/ansible/roles/keycloak_remote_installer/README.md @@ -15,7 +15,7 @@ See `defaults/main.yml` for default values. ### Other - `update_system_packages`: Whether to update the system packages. Defaults to `no`. - `install_java`: Whether to install OpenJDK on the system. Defaults to `yes`. -- `java_version`: Version of OpenJDK to be installed. Defaults to `21`. +- `java_version`: Version of OpenJDK to be installed. Defaults to `25`. ## Example Playbook diff --git a/.github/scripts/ansible/roles/keycloak_remote_installer/defaults/main.yml b/.github/scripts/ansible/roles/keycloak_remote_installer/defaults/main.yml index a853d38849c..506d551c84b 100644 --- a/.github/scripts/ansible/roles/keycloak_remote_installer/defaults/main.yml +++ b/.github/scripts/ansible/roles/keycloak_remote_installer/defaults/main.yml @@ -3,4 +3,4 @@ kc_home: /opt/keycloak m2_home: ~/.m2 update_system_packages: no install_java: yes -java_version: 21 +java_version: 25 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f61009f6ea4..071e9ca4ca5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -162,6 +162,8 @@ jobs: - id: integration-test-setup name: Integration test setup uses: ./.github/actions/integration-test-setup + with: + jdk-version: '21' - name: Build adapter distributions run: ./mvnw install -DskipTests -f distribution/pom.xml @@ -193,6 +195,8 @@ jobs: - id: integration-test-setup name: Integration test setup uses: ./.github/actions/integration-test-setup + with: + jdk-version: '21' - name: Build adapter distributions run: ./mvnw install -DskipTests -f distribution/pom.xml @@ -302,7 +306,7 @@ jobs: matrix: os: [ubuntu-latest, windows-latest] dist: [temurin] - version: [17, 25] + version: [17, 21] fail-fast: false runs-on: ${{ matrix.os }} steps: @@ -1103,6 +1107,8 @@ jobs: - id: integration-test-setup name: Integration test setup uses: ./.github/actions/integration-test-setup + with: + jdk-version: 21 # Keycloak 24 is not compatible with Java 25+ - name: Run Migration Tests run: | diff --git a/distribution/maven-plugins/pom.xml b/distribution/maven-plugins/pom.xml index 4eff4b908a6..0737369d598 100644 --- a/distribution/maven-plugins/pom.xml +++ b/distribution/maven-plugins/pom.xml @@ -32,7 +32,7 @@ org.codehaus.groovy groovy-all - 3.0.21 + 3.0.25 pom diff --git a/docs/documentation/README.md b/docs/documentation/README.md index 4bc1768ad85..3c8686b798b 100644 --- a/docs/documentation/README.md +++ b/docs/documentation/README.md @@ -46,7 +46,7 @@ To build the REST API documentation and the Javadoc: - Export the `JAVA_HOME` variable, for example: ``` - export JAVA_HOME=/usr/lib/jvm/java-21-openjdk + export JAVA_HOME=/usr/lib/jvm/java-25-openjdk ``` (without this, you may get the following error: `Unable to find javadoc command: The environment variable JAVA_HOME is not correctly set.`) - Run: diff --git a/docs/documentation/release_notes/topics/26_6_0.adoc b/docs/documentation/release_notes/topics/26_6_0.adoc index bafa53a65ba..75645ee3f59 100644 --- a/docs/documentation/release_notes/topics/26_6_0.adoc +++ b/docs/documentation/release_notes/topics/26_6_0.adoc @@ -31,3 +31,7 @@ You can specify these headers via the general parent option `telemetry-header-` for OpenTelemetry Logs, or `telemetry-metrics-header-
` for OpenTelemetry Metrics. For more details, see the link:{telemetryguide_link}[{telemetryguide_name}] guide. + += Java 25 support + +{project_name} now supports running with JRE 25. diff --git a/docs/guides/getting-started/getting-started-zip.adoc b/docs/guides/getting-started/getting-started-zip.adoc index b40e610205a..4db0685fde6 100644 --- a/docs/guides/getting-started/getting-started-zip.adoc +++ b/docs/guides/getting-started/getting-started-zip.adoc @@ -13,7 +13,7 @@ summary="Get started with {project_name} on a physical or virtual server."> include::templates/hw-requirements.adoc[] -Make sure you have https://openjdk.java.net/[OpenJDK 21] installed. +Make sure you have https://openjdk.java.net/[OpenJDK 25] installed. == Download {project_name} diff --git a/docs/guides/observability/partials/jgrp_metrics.adoc b/docs/guides/observability/partials/jgrp_metrics.adoc index e3e9b34d359..5adc33f4bdf 100644 --- a/docs/guides/observability/partials/jgrp_metrics.adoc +++ b/docs/guides/observability/partials/jgrp_metrics.adoc @@ -85,7 +85,7 @@ A retransmission mechanism ensures a reliable communication with an increase of TIP: In a healthy cluster, the thread pool should never be closer to its maximum size (by default, `200` threads). -NOTE: Thread pool metrics are not available with virtual threads. Virtual threads are enabled by default when running with OpenJDK 21. +NOTE: Thread pool metrics are not available with virtual threads. Virtual threads are enabled by default when running with OpenJDK 21 and later. IMPORTANT: The metric name depends on the JGroups transport protocol in use. The default transport protocol is TCP. diff --git a/operator/pom.xml b/operator/pom.xml index c7fe147977d..5519cebc5e2 100644 --- a/operator/pom.xml +++ b/operator/pom.xml @@ -271,6 +271,17 @@ + + + org.apache.maven.plugins + maven-compiler-plugin + + + -proc:full + + + + maven-surefire-plugin diff --git a/quarkus/dist/src/main/content/bin/kc.bat b/quarkus/dist/src/main/content/bin/kc.bat index 2ed30178a4f..fed43b1b50a 100644 --- a/quarkus/dist/src/main/content/bin/kc.bat +++ b/quarkus/dist/src/main/content/bin/kc.bat @@ -129,10 +129,12 @@ if not "x%JAVA_OPTS%" == "x" ( ) @REM See also https://github.com/wildfly/wildfly-core/blob/7e5624cf92ebe4b64a4793a8c0b2a340c0d6d363/core-feature-pack/common/src/main/resources/content/bin/common.sh#L57-L60 +@REM java.base/java.lang=ALL-UNNAMED is required for JBoss Threads, see e.g. https://github.com/quarkusio/quarkus/pull/47637 and relevant https://github.com/quarkusio/quarkus/discussions/51041 +@REM --enable-native-access=ALL-UNNAMED is required for Infinispan: https://github.com/infinispan/infinispan/issues/15765#issuecomment-3839985807 if not "x%JAVA_ADD_OPENS%" == "x" ( echo "JAVA_ADD_OPENS already set in environment; overriding default settings" ) else ( - set "JAVA_ADD_OPENS=--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED" + set "JAVA_ADD_OPENS=--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --enable-native-access=ALL-UNNAMED" ) set "JAVA_OPTS=%JAVA_OPTS% %JAVA_ADD_OPENS%" diff --git a/quarkus/dist/src/main/content/bin/kc.sh b/quarkus/dist/src/main/content/bin/kc.sh index 88a6fb58ab4..00f59dfac6e 100644 --- a/quarkus/dist/src/main/content/bin/kc.sh +++ b/quarkus/dist/src/main/content/bin/kc.sh @@ -112,8 +112,10 @@ else fi # See also https://github.com/wildfly/wildfly-core/blob/7e5624cf92ebe4b64a4793a8c0b2a340c0d6d363/core-feature-pack/common/src/main/resources/content/bin/common.sh#L57-L60 +# java.base/java.lang=ALL-UNNAMED is required for JBoss Threads, see e.g. https://github.com/quarkusio/quarkus/pull/47637 and relevant https://github.com/quarkusio/quarkus/discussions/51041 +# --enable-native-access=ALL-UNNAMED is required for Infinispan: https://github.com/infinispan/infinispan/issues/15765#issuecomment-3839985807 if [ -z "$JAVA_ADD_OPENS" ]; then - JAVA_ADD_OPENS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED" + JAVA_ADD_OPENS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --enable-native-access=ALL-UNNAMED" else echo "JAVA_ADD_OPENS already set in environment; overriding default settings" fi diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml index 3a3cd66e6df..9b284661b63 100644 --- a/testsuite/integration-arquillian/pom.xml +++ b/testsuite/integration-arquillian/pom.xml @@ -56,7 +56,6 @@ 2.0.3 2.2.3 1.8.0 - 1.14.13 1.9.8.Final diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml index f4b86230b04..81a0badd8dc 100644 --- a/testsuite/integration-arquillian/tests/base/pom.xml +++ b/testsuite/integration-arquillian/tests/base/pom.xml @@ -755,7 +755,6 @@ net.bytebuddy byte-buddy - ${byte-buddy.version} diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index 840fe0becc4..e54b9b4a88b 100644 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -1493,7 +1493,6 @@ net.bytebuddy byte-buddy - ${byte-buddy.version} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java index 93592831ae8..b6862cfac09 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/infinispan/CacheExpirationTest.java @@ -17,9 +17,10 @@ package org.keycloak.testsuite.model.infinispan; import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.lang.management.ManagementFactory; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.Instant; import java.util.Collections; import java.util.Objects; @@ -143,12 +144,26 @@ public class CacheExpirationTest extends KeycloakModelTest { // This is synchronized as it doesn't make sense to run this in parallel with multiple threads // as each invocation will run a garbage collection anyway. public synchronized Integer getNumberOfInstancesOfClass(Class c, String pid) { - Process proc; + log.debug("PID: " + pid); + + Path tempFile = null; try { // running jmap command will also trigger a garbage collection on the VM, but that might be VM specific // a test run with adding "-verbose:gc" showed the message "GC(23) Pause Full (Heap Inspection Initiated GC)" that // indicates a full GC run - proc = Runtime.getRuntime().exec("jmap -histo:live " + pid); + + tempFile = Files.createTempFile("jmap-output", ".txt"); // not consuming the output directly to avoid potential deadlock + + Process proc = new ProcessBuilder("jmap", "-histo:live", pid) + .redirectOutput(tempFile.toFile()) + .redirectError(ProcessBuilder.Redirect.INHERIT) + .start(); + + boolean finished = proc.waitFor(30, TimeUnit.SECONDS); + if (!finished) { + proc.destroyForcibly(); + throw new RuntimeException("jmap timed out!"); + } try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()))) { AtomicInteger matchingLines = new AtomicInteger(); @@ -165,10 +180,18 @@ public class CacheExpirationTest extends KeycloakModelTest { .map(m -> Integer.valueOf(m.group(1))) .orElseGet(() -> matchingLines.get() == 0 ? null : 0); } - } catch (IOException ex) { + } catch (Exception ex) { log.debug(ex); - Assume.assumeTrue("jmap not found or unsupported", false); + Assume.assumeTrue("jmap not found, unsupported or failed", false); return null; + } finally { + if (tempFile != null) { + try { + Files.deleteIfExists(tempFile); + } catch (Exception ex) { + log.debug(ex); + } + } } } }