Ensure that Java's ForkJoinPool is initialized with Quarkus' ThreadPoolFactory
Closes #30120 Signed-off-by: Alexander Schwartz <aschwart@redhat.com>
This commit is contained in:
parent
20368b35b9
commit
1b821f3267
4 changed files with 27 additions and 3 deletions
3
quarkus/dist/src/main/content/bin/kc.bat
vendored
3
quarkus/dist/src/main/content/bin/kc.bat
vendored
|
@ -165,7 +165,8 @@ if "x%JAVA%" == "x" (
|
|||
|
||||
set CLASSPATH_OPTS="%DIRNAME%..\lib\quarkus-run.jar"
|
||||
|
||||
set JAVA_RUN_OPTS=%JAVA_OPTS% -Dkc.home.dir="%DIRNAME%.." -Djboss.server.config.dir="%DIRNAME%..\conf" -Dkeycloak.theme.dir="%DIRNAME%..\themes" %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS%
|
||||
rem The property 'java.util.concurrent.ForkJoinPool.common.threadFactory' is set here, as a Java Agent or enabling JMX might initialize the factory before Quarkus can set the property in JDK21+.
|
||||
set JAVA_RUN_OPTS=-Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory %JAVA_OPTS% -Dkc.home.dir="%DIRNAME%.." -Djboss.server.config.dir="%DIRNAME%..\conf" -Dkeycloak.theme.dir="%DIRNAME%..\themes" %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS%
|
||||
|
||||
set OPTIMIZED_OPTION=--optimized
|
||||
set HELP_LONG_OPTION=--help
|
||||
|
|
3
quarkus/dist/src/main/content/bin/kc.sh
vendored
3
quarkus/dist/src/main/content/bin/kc.sh
vendored
|
@ -157,7 +157,8 @@ esceval_args() {
|
|||
|
||||
JAVA_RUN_OPTS=$(echo "$JAVA_OPTS" | xargs printf '%s\n' | esceval_args)
|
||||
|
||||
JAVA_RUN_OPTS="$JAVA_RUN_OPTS $SERVER_OPTS -cp $CLASSPATH_OPTS io.quarkus.bootstrap.runner.QuarkusEntryPoint ${CONFIG_ARGS#?}"
|
||||
# The property 'java.util.concurrent.ForkJoinPool.common.threadFactory' is set here, as a Java Agent or enabling JMX might initialize the factory before Quarkus can set the property in JDK21+.
|
||||
JAVA_RUN_OPTS="-Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory $JAVA_RUN_OPTS $SERVER_OPTS -cp $CLASSPATH_OPTS io.quarkus.bootstrap.runner.QuarkusEntryPoint ${CONFIG_ARGS#?}"
|
||||
|
||||
if [ "$PRINT_ENV" = "true" ]; then
|
||||
echo "Using JAVA_OPTS: $JAVA_OPTS"
|
||||
|
|
|
@ -29,6 +29,7 @@ import static org.keycloak.quarkus.runtime.cli.command.Start.isDevProfileNotAllo
|
|||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.keycloak.common.profile.ProfileException;
|
||||
|
@ -56,6 +57,8 @@ import io.quarkus.runtime.annotations.QuarkusMain;
|
|||
public class KeycloakMain implements QuarkusApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ensureForkJoinPoolThreadFactoryHasBeenSetToQuarkus();
|
||||
|
||||
System.setProperty("kc.version", Version.VERSION);
|
||||
List<String> cliArgs = null;
|
||||
try {
|
||||
|
@ -96,6 +99,25 @@ public class KeycloakMain implements QuarkusApplication {
|
|||
parseAndRun(cliArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the property for the ForkJoinPool factory set by Quarkus matches the actual factory.
|
||||
* If this is not the case, the classloader for those threads is not set correctly, and for example loading configurations
|
||||
* via SmallRye is unreliable. This can happen if a Java Agent or JMX initializes the ForkJoinPool before Java's main method is run.
|
||||
*/
|
||||
private static void ensureForkJoinPoolThreadFactoryHasBeenSetToQuarkus() {
|
||||
// At this point, the settings from the CLI are no longer visible as they have been overwritten in the QuarkusEntryPoint.
|
||||
// Therefore, the only thing we can do is to check if the thread pool class name is the same as in the configuration.
|
||||
final String FORK_JOIN_POOL_COMMON_THREAD_FACTORY = "java.util.concurrent.ForkJoinPool.common.threadFactory";
|
||||
String sf = System.getProperty(FORK_JOIN_POOL_COMMON_THREAD_FACTORY);
|
||||
//noinspection resource
|
||||
if (!ForkJoinPool.commonPool().getFactory().getClass().getName().equals(sf)) {
|
||||
Logger.getLogger(KeycloakMain.class).errorf("The ForkJoinPool has been initialized with the wrong thread factory. The property '%s' should be set on the Java CLI to ensure Java's ForkJoinPool will always be initialized with '%s' even if there are Java agents which might initialize logging or other capabilities earlier than the main method.",
|
||||
FORK_JOIN_POOL_COMMON_THREAD_FACTORY,
|
||||
sf);
|
||||
throw new RuntimeException("The ForkJoinPool has been initialized with the wrong thread factory");
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleUsageError(String message) {
|
||||
handleUsageError(message, null);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError --add-opens=java.base/java.security=ALL-UNNAMED</argLine>
|
||||
<argLine>-Djdk.net.hosts.file=${project.build.testOutputDirectory}/hosts_file -XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError --add-opens=java.base/java.security=ALL-UNNAMED -Djava.util.concurrent.ForkJoinPool.common.threadFactory=io.quarkus.bootstrap.forkjoin.QuarkusForkJoinWorkerThreadFactory</argLine>
|
||||
<systemPropertyVariables>
|
||||
<kc.quarkus.tests.dist>${kc.quarkus.tests.dist}</kc.quarkus.tests.dist>
|
||||
</systemPropertyVariables>
|
||||
|
|
Loading…
Reference in a new issue