From 91e07e4023fdc5b705eb61e7ceeefd35ec504aa2 Mon Sep 17 00:00:00 2001 From: Tomas Hofman Date: Wed, 20 Sep 2023 13:55:41 +0200 Subject: [PATCH] WFCORE-6505 Avoid creating duplicate thread groups on server reload --- .../java/org/jboss/as/cli/gui/JConsoleCLIPlugin.java | 8 ++++++-- ...tModelControllerOperationHandlerFactoryService.java | 7 ++++++- .../deployment/scanner/DeploymentScannerAdd.java | 7 ++++++- .../host/controller/DomainModelControllerService.java | 8 +++++++- .../as/host/controller/HostControllerService.java | 6 +++--- .../controller/ProcessControllerConnectionService.java | 6 +++++- .../ServerToHostOperationHandlerFactoryService.java | 6 +++++- .../main/java/org/jboss/as/server/ServerService.java | 10 +++++++--- .../as/server/deployment/DeploymentMountProvider.java | 7 ++++++- .../deployment/module/TempFileProviderService.java | 7 ++++++- .../management/util/DomainControllerClientConfig.java | 7 +++++-- .../org/jboss/as/threads/ThreadFactoryService.java | 8 +++++++- 12 files changed, 69 insertions(+), 18 deletions(-) diff --git a/cli/src/main/java/org/jboss/as/cli/gui/JConsoleCLIPlugin.java b/cli/src/main/java/org/jboss/as/cli/gui/JConsoleCLIPlugin.java index 4e565c27be5..735e238a386 100644 --- a/cli/src/main/java/org/jboss/as/cli/gui/JConsoleCLIPlugin.java +++ b/cli/src/main/java/org/jboss/as/cli/gui/JConsoleCLIPlugin.java @@ -187,10 +187,9 @@ private boolean connectUsingRemoting(CommandContext cmdCtx, RemotingMBeanServerC } private ExecutorService createExecutor() { - final ThreadGroup group = new ThreadGroup("management-client-thread"); final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(group, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null); } }); return EnhancedQueueExecutor.DISABLE_HINT ? @@ -246,4 +245,9 @@ private void configureMyJInternalFrame() { } } } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("management-client-thread"); + } } \ No newline at end of file diff --git a/controller/src/main/java/org/jboss/as/controller/remote/AbstractModelControllerOperationHandlerFactoryService.java b/controller/src/main/java/org/jboss/as/controller/remote/AbstractModelControllerOperationHandlerFactoryService.java index a8c1c07b094..9aec8c3ba33 100644 --- a/controller/src/main/java/org/jboss/as/controller/remote/AbstractModelControllerOperationHandlerFactoryService.java +++ b/controller/src/main/java/org/jboss/as/controller/remote/AbstractModelControllerOperationHandlerFactoryService.java @@ -88,7 +88,7 @@ public synchronized void start(StartContext context) throws StartException { final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("management-handler-thread"), Boolean.FALSE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G - %t", null, null); } }); if (EnhancedQueueExecutor.DISABLE_HINT) { @@ -161,4 +161,9 @@ protected final ExecutorService getClientRequestExecutor() { return clientRequestExecutor; } + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("management-handler-thread"); + } + } diff --git a/deployment-scanner/src/main/java/org/jboss/as/server/deployment/scanner/DeploymentScannerAdd.java b/deployment-scanner/src/main/java/org/jboss/as/server/deployment/scanner/DeploymentScannerAdd.java index 5826ccdbf09..d54c4001be1 100644 --- a/deployment-scanner/src/main/java/org/jboss/as/server/deployment/scanner/DeploymentScannerAdd.java +++ b/deployment-scanner/src/main/java/org/jboss/as/server/deployment/scanner/DeploymentScannerAdd.java @@ -233,7 +233,7 @@ private void recordCapabilitiesAndRequirements(final OperationContext context, R static ScheduledExecutorService createScannerExecutorService() { final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public ThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("DeploymentScanner-threads"), Boolean.FALSE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G - %t", null, null); } }); return Executors.newScheduledThreadPool(2, threadFactory); @@ -303,4 +303,9 @@ public Set getUnrelatedDeployments(ModelNode owner) { return Collections.emptySet(); } } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("DeploymentScanner-threads"); + } } diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/DomainModelControllerService.java b/host-controller/src/main/java/org/jboss/as/host/controller/DomainModelControllerService.java index ba13252f164..1845ec332c4 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/DomainModelControllerService.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/DomainModelControllerService.java @@ -540,7 +540,7 @@ public void start(StartContext context) throws StartException { prepareStepHandler.setExecutorService(executorService); ThreadFactory pingerThreadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("proxy-pinger-threads"), Boolean.TRUE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.TRUE, null, "%G - %t", null, null); } }); pingScheduler = Executors.newScheduledThreadPool(PINGER_POOL_SIZE, pingerThreadFactory); @@ -1799,4 +1799,10 @@ public void propertyChange(PropertyChangeEvent evt) { } } } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("proxy-pinger-threads"); + } + } diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerService.java b/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerService.java index d8fc394e405..e0e5bb3b456 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerService.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/HostControllerService.java @@ -84,10 +84,10 @@ public class HostControllerService implements Service() { public JBossThreadFactory run() { - return new JBossThreadFactory(threadGroup, Boolean.FALSE, null, "%G - %t", null, null); + return new JBossThreadFactory(THREAD_GROUP, Boolean.FALSE, null, "%G - %t", null, null); } }); private final HostControllerEnvironment environment; @@ -215,7 +215,7 @@ public void start(StartContext context) throws StartException { ConsoleAvailabilityService.addService(serviceTarget, bootstrapListener::logAdminConsole); DomainModelControllerService.addService(serviceTarget, environment, runningModeControl, processState, - bootstrapListener, hostPathManagerService, capabilityRegistry, threadGroup); + bootstrapListener, hostPathManagerService, capabilityRegistry, THREAD_GROUP); } @Override diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/ProcessControllerConnectionService.java b/host-controller/src/main/java/org/jboss/as/host/controller/ProcessControllerConnectionService.java index 25425403d6e..b5d95b74d87 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/ProcessControllerConnectionService.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/ProcessControllerConnectionService.java @@ -83,7 +83,7 @@ public synchronized void start(StartContext context) throws StartException { try { final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("ProcessControllerConnection-thread"), Boolean.FALSE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G - %t", null, null); } }); final ExecutorService executorService; @@ -216,4 +216,8 @@ public synchronized ProcessControllerClient getClient() throws IllegalStateExcep return client; } + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("ProcessControllerConnection-thread"); + } } diff --git a/host-controller/src/main/java/org/jboss/as/host/controller/mgmt/ServerToHostOperationHandlerFactoryService.java b/host-controller/src/main/java/org/jboss/as/host/controller/mgmt/ServerToHostOperationHandlerFactoryService.java index f38049f96e4..ee7af3c5405 100644 --- a/host-controller/src/main/java/org/jboss/as/host/controller/mgmt/ServerToHostOperationHandlerFactoryService.java +++ b/host-controller/src/main/java/org/jboss/as/host/controller/mgmt/ServerToHostOperationHandlerFactoryService.java @@ -68,7 +68,7 @@ public class ServerToHostOperationHandlerFactoryService implements ManagementCha private final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("server-registration-threads"), Boolean.FALSE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G - %t", null, null); } }); private volatile ExecutorService registrations; @@ -123,4 +123,8 @@ public ManagementChannelHandler startReceiving(final Channel channel) { return channelHandler; } + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("server-registration-threads"); + } } diff --git a/server/src/main/java/org/jboss/as/server/ServerService.java b/server/src/main/java/org/jboss/as/server/ServerService.java index 7600028e079..b7d46c58129 100644 --- a/server/src/main/java/org/jboss/as/server/ServerService.java +++ b/server/src/main/java/org/jboss/as/server/ServerService.java @@ -232,11 +232,10 @@ public static void addService(final ServiceTarget serviceTarget, final Bootstrap final SuspendController suspendController) { // Install Executor services - final ThreadGroup threadGroup = new ThreadGroup("ServerService ThreadGroup"); final String namePattern = "ServerService Thread Pool -- %t"; final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public ThreadFactory run() { - return new JBossThreadFactory(threadGroup, Boolean.FALSE, null, namePattern, null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, namePattern, null, null); } }); @@ -276,7 +275,7 @@ public ThreadFactory run() { serviceBuilder.install(); - ExternalManagementRequestExecutor.install(serviceTarget, threadGroup, EXECUTOR_CAPABILITY.getCapabilityServiceName()); + ExternalManagementRequestExecutor.install(serviceTarget, ThreadGroupHolder.THREAD_GROUP, EXECUTOR_CAPABILITY.getCapabilityServiceName()); } public synchronized void start(final StartContext context) throws StartException { @@ -694,4 +693,9 @@ public synchronized ScheduledExecutorService getValue() throws IllegalStateExcep return scheduledExecutorService; } } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("ServerService ThreadGroup"); + } } diff --git a/server/src/main/java/org/jboss/as/server/deployment/DeploymentMountProvider.java b/server/src/main/java/org/jboss/as/server/deployment/DeploymentMountProvider.java index 29fd6700146..18c0f034ad3 100644 --- a/server/src/main/java/org/jboss/as/server/deployment/DeploymentMountProvider.java +++ b/server/src/main/java/org/jboss/as/server/deployment/DeploymentMountProvider.java @@ -120,7 +120,7 @@ public void start(StartContext context) throws StartException { try { final JBossThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("ServerDeploymentRepository-temp-threads"), true, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, true, null, "%G - %t", null, null); } }); scheduledExecutorService = Executors.newScheduledThreadPool(2, threadFactory); @@ -167,5 +167,10 @@ public void run() { } } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("ServerDeploymentRepository-temp-threads"); + } } } diff --git a/server/src/main/java/org/jboss/as/server/deployment/module/TempFileProviderService.java b/server/src/main/java/org/jboss/as/server/deployment/module/TempFileProviderService.java index 9a90b503b03..1062b777645 100644 --- a/server/src/main/java/org/jboss/as/server/deployment/module/TempFileProviderService.java +++ b/server/src/main/java/org/jboss/as/server/deployment/module/TempFileProviderService.java @@ -52,7 +52,7 @@ public class TempFileProviderService implements Service { try { final JBossThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public JBossThreadFactory run() { - return new JBossThreadFactory(new ThreadGroup("TempFileProviderService-temp-threads"), Boolean.TRUE, null, "%G - %t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.TRUE, null, "%G - %t", null, null); } }); ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(0, threadFactory); @@ -87,4 +87,9 @@ public TempFileProvider getValue() throws IllegalStateException { public static TempFileProvider provider() { return PROVIDER; } + + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("TempFileProviderService-temp-threads"); + } } diff --git a/testsuite/shared/src/main/java/org/jboss/as/test/integration/domain/management/util/DomainControllerClientConfig.java b/testsuite/shared/src/main/java/org/jboss/as/test/integration/domain/management/util/DomainControllerClientConfig.java index ebb9f16c6cd..671b4ba8b8b 100644 --- a/testsuite/shared/src/main/java/org/jboss/as/test/integration/domain/management/util/DomainControllerClientConfig.java +++ b/testsuite/shared/src/main/java/org/jboss/as/test/integration/domain/management/util/DomainControllerClientConfig.java @@ -54,10 +54,9 @@ public class DomainControllerClientConfig implements Closeable { private static final AtomicInteger executorCount = new AtomicInteger(); static ExecutorService createDefaultExecutor() { - final ThreadGroup group = new ThreadGroup("domain-mgmt-client-thread"); final ThreadFactory threadFactory = doPrivileged(new PrivilegedAction() { public ThreadFactory run() { - return new JBossThreadFactory(group, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null); + return new JBossThreadFactory(ThreadGroupHolder.THREAD_GROUP, Boolean.FALSE, null, "%G " + executorCount.incrementAndGet() + "-%t", null, null); } }); return new ThreadPoolExecutor(4, 4, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue(256), threadFactory); @@ -115,4 +114,8 @@ static DomainControllerClientConfig create(final ExecutorService executorService return new DomainControllerClientConfig(endpoint, executorService, destroyExecutor); } + // Wrapper class to delay thread group creation until when it's needed. + private static class ThreadGroupHolder { + private static final ThreadGroup THREAD_GROUP = new ThreadGroup("domain-mgmt-client-thread"); + } } diff --git a/threads/src/main/java/org/jboss/as/threads/ThreadFactoryService.java b/threads/src/main/java/org/jboss/as/threads/ThreadFactoryService.java index 2c85cc6dc82..cbf7bc66b30 100644 --- a/threads/src/main/java/org/jboss/as/threads/ThreadFactoryService.java +++ b/threads/src/main/java/org/jboss/as/threads/ThreadFactoryService.java @@ -23,6 +23,8 @@ package org.jboss.as.threads; import java.security.PrivilegedAction; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ThreadFactory; import org.jboss.msc.service.Service; import org.jboss.msc.service.StartContext; @@ -36,6 +38,9 @@ * @author David M. Lloyd */ public final class ThreadFactoryService implements Service { + + private static final Map THREAD_GROUP_CACHE = new ConcurrentHashMap<>(); + private String threadGroupName; private Integer priority; private String namePattern; @@ -67,7 +72,8 @@ public synchronized void setNamePattern(final String namePattern) { @Override public synchronized void start(final StartContext context) throws StartException { - final ThreadGroup threadGroup = (threadGroupName != null) ? new ThreadGroup(threadGroupName) : null; + final ThreadGroup threadGroup = THREAD_GROUP_CACHE.computeIfAbsent(threadGroupName, name -> + name != null ? new ThreadGroup(name) : null); value = doPrivileged(new PrivilegedAction() { public ThreadFactory run() { return new JBossThreadFactory(threadGroup, Boolean.FALSE, priority, namePattern, null, null);