From ae9a6345c229356d1ea8b536bab4535ca8e8ead7 Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Wed, 21 Jul 2021 10:30:46 +0100 Subject: [PATCH] Optimise the strategy we use to reset the classloader in the Common ForkJoin ThreadPool --- .../bootstrap/ForkJoinClassLoading.java | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/ForkJoinClassLoading.java b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/ForkJoinClassLoading.java index 784242bcdd81a..f9fedc368ebcb 100644 --- a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/ForkJoinClassLoading.java +++ b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/ForkJoinClassLoading.java @@ -20,31 +20,42 @@ public class ForkJoinClassLoading { * Really we should just not use the common pool at all. */ public static void setForkJoinClassLoader(ClassLoader classLoader) { - CountDownLatch allDone = new CountDownLatch(ForkJoinPool.getCommonPoolParallelism()); - CountDownLatch taskRelease = new CountDownLatch(1); - for (int i = 0; i < ForkJoinPool.getCommonPoolParallelism(); ++i) { - ForkJoinPool.commonPool().execute(new Runnable() { - @Override - public void run() { - Thread.currentThread().setContextClassLoader(classLoader); - allDone.countDown(); - try { - taskRelease.await(); - } catch (InterruptedException e) { - log.error("Failed to set fork join ClassLoader", e); + final ForkJoinPool commonPool = ForkJoinPool.commonPool(); + + final int activeThreadCount = commonPool.getActiveThreadCount(); + + //The following approach is rather heavy, but there's good chances that there are actually no active threads, + //so skip it in this case. + //Additionally, if we can skip this this will prevent us from actually forcing to start all threads in the pool. + if (activeThreadCount > 0) { + //TODO we could theoretically improve this by using the system property java.util.concurrent.ForkJoinPool.common.threadFactory + //and force the common pool to register created threads so that we can reach and reset them. + CountDownLatch allDone = new CountDownLatch(ForkJoinPool.getCommonPoolParallelism()); + CountDownLatch taskRelease = new CountDownLatch(1); + for (int i = 0; i < ForkJoinPool.getCommonPoolParallelism(); ++i) { + commonPool.execute(new Runnable() { + @Override + public void run() { + Thread.currentThread().setContextClassLoader(classLoader); + allDone.countDown(); + try { + taskRelease.await(); + } catch (InterruptedException e) { + log.error("Failed to set fork join ClassLoader", e); + } } + }); + } + try { + if (!allDone.await(1, TimeUnit.SECONDS)) { + log.error( + "Timed out trying to set fork join ClassLoader, this should never happen unless something has tied up a fork join thread before the app launched"); } - }); - } - try { - if (!allDone.await(1, TimeUnit.SECONDS)) { - log.error( - "Timed out trying to set fork join ClassLoader, this should never happen unless something has tied up a fork join thread before the app launched"); + } catch (InterruptedException e) { + log.error("Failed to set fork join ClassLoader", e); + } finally { + taskRelease.countDown(); } - } catch (InterruptedException e) { - log.error("Failed to set fork join ClassLoader", e); - } finally { - taskRelease.countDown(); } } }