diff --git a/core-common/pom.xml b/core-common/pom.xml
index 7a187e01fc..357b2e95f6 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -693,6 +693,157 @@
+
+ build.jdk20-
+
+ [1.8,21)
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add.java20-
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+
+
+
+ build.jdk21
+
+ [21,)
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ add.java20-
+ generate-sources
+
+ add-source
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+
+
+ 21
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ validate
+
+ run
+
+
+
+ Building for JDK 21+
+
+
+
+
+ compile-java21
+ process-resources
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
+
+ copyJDK21FilesToMultiReleaseJar
+
+
+
+ target/classes-java21/org/glassfish/jersey/innate/VirtualThreadSupport.class
+
+ [1.8,21)
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ true
+
+
+ copy-jdk21-sources
+ prepare-package
+
+ copy-resources
+
+
+ ${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/21/org/glassfish/jersey/innate
+
+
+ ${java21.sourceDirectory}/org/glassfish/jersey/innate
+
+
+
+
+
+ copy-jdk21-classes-to-meta-inf
+ prepare-package
+
+ copy-resources
+
+
+ ${project.build.outputDirectory}/META-INF/versions/21
+
+
+ ${java21.build.outputDirectory}
+
+
+
+
+
+
+
+
+ securityOff
@@ -739,6 +890,8 @@
${project.basedir}/src/main/java8${project.build.directory}/classes-java11${project.basedir}/src/main/java11
+ ${project.build.directory}/classes-java21
+ ${project.basedir}/src/main/java21
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
index 7c1cf4a1af..05e77cb59d 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CommittingOutputStream.java
@@ -23,9 +23,9 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.glassfish.jersey.innate.VirtualThreadSupport;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.guava.Preconditions;
-import org.glassfish.jersey.internal.util.JdkVersion;
/**
* A committing output stream with optional serialized entity buffering functionality
@@ -59,7 +59,7 @@
public final class CommittingOutputStream extends OutputStream {
private static final Logger LOGGER = Logger.getLogger(CommittingOutputStream.class.getName());
- private static final boolean JDK_21 = JdkVersion.getJdkVersion().getMajor() > 20;
+ private final boolean isVirtualThread = VirtualThreadSupport.isVirtualThread();
/**
* Null stream provider.
@@ -278,7 +278,7 @@ private void flushBuffer(boolean endOfStream) throws IOException {
commitStream(currentSize);
if (buffer != null) {
- if (adaptedOutput != null && JDK_21) {
+ if (isVirtualThread && adaptedOutput != null) {
adaptedOutput.write(buffer.toByteArray());
} else {
// Virtual thread in JDK 21 are blocked by synchronized writeTo
diff --git a/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java b/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java
new file mode 100644
index 0000000000..90cafba6a2
--- /dev/null
+++ b/core-common/src/main/java20-/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+ /**
+ * Do not instantiate.
+ */
+ private VirtualThreadSupport() {
+ throw new IllegalStateException();
+ }
+
+ /**
+ * Informs whether the given {@link Thread} is virtual.
+ * @return true when the current thread is virtual.
+ */
+ public static boolean isVirtualThread() {
+ return false;
+ }
+}
diff --git a/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java b/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java
new file mode 100644
index 0000000000..74f58ba9da
--- /dev/null
+++ b/core-common/src/main/java21/org/glassfish/jersey/innate/VirtualThreadSupport.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate;
+
+/**
+ * Utility class for the virtual thread support.
+ */
+public final class VirtualThreadSupport {
+
+ /**
+ * Do not instantiate.
+ */
+ private VirtualThreadSupport() {
+ throw new IllegalStateException();
+ }
+
+ /**
+ * Informs whether the given {@link Thread} is virtual.
+ * @return true when the current thread is virtual.
+ */
+ public static boolean isVirtualThread() {
+ return Thread.currentThread().isVirtual();
+ }
+}