From d2a836769feceb6cac68ef4bec5e01368989c6a8 Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Mon, 17 Mar 2025 22:30:24 +0900 Subject: [PATCH 1/2] Document requirements for reflective access in ExecutorServiceMetrics See https://github.com/micrometer-metrics/micrometer/pull/6008#pullrequestreview-2689545471 Signed-off-by: Johnny Lim --- docs/modules/ROOT/pages/reference/jvm.adoc | 6 ++++++ .../instrument/binder/jvm/ExecutorServiceMetrics.java | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/modules/ROOT/pages/reference/jvm.adoc b/docs/modules/ROOT/pages/reference/jvm.adoc index ac09c6b41e..a19099ff1d 100644 --- a/docs/modules/ROOT/pages/reference/jvm.adoc +++ b/docs/modules/ROOT/pages/reference/jvm.adoc @@ -45,6 +45,12 @@ another. The reported value underestimates the actual total number of steals whe * `executor.parallelism` (`Gauge`): The targeted parallelism level of this pool. * `executor.pool.size` (`Gauge`): The current number of threads in the pool. +To use the following `ExecutorService` instances, `--add-opens java.base/java.util.concurrent=ALL-UNNAMED` is required: + +* `Executors.newSingleThreadScheduledExecutor()` +* `Executors.newSingleThreadExecutor()` +* `Executors.newThreadPerTaskExecutor()` + == Java 21 Metrics Micrometer provides support for https://openjdk.org/jeps/444[virtual threads] released in Java 21. In order to utilize it, you need to add the `io.micrometer:micrometer-java21` dependency to your classpath to use the binder: diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java index c63ba85f4d..de16b65d04 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java @@ -50,6 +50,14 @@ * {@link ExecutorService}, like {@link TimedExecutorService}. Make sure to pass the * underlying, unwrapped ExecutorService to this MeterBinder, if it is wrapped in another * type. + *

+ * To use the following {@link ExecutorService} instances, + * {@literal --add-opens java.base/java.util.concurrent=ALL-UNNAMED} is required: + *

* * @author Jon Schneider * @author Clint Checketts @@ -315,14 +323,17 @@ else if (executorService instanceof ForkJoinPool) { monitor(registry, (ForkJoinPool) executorService); } else if (allowIllegalReflectiveAccess) { + // For Executors.newSingleThreadScheduledExecutor() if (className.equals("java.util.concurrent.Executors$DelegatedScheduledExecutorService")) { monitor(registry, unwrapThreadPoolExecutor(executorService, executorService.getClass())); } + // For Executors.newSingleThreadExecutor() else if (className.equals("java.util.concurrent.Executors$FinalizableDelegatedExecutorService") || className.equals("java.util.concurrent.Executors$AutoShutdownDelegatedExecutorService")) { monitor(registry, unwrapThreadPoolExecutor(executorService, executorService.getClass().getSuperclass())); } + // For Executors.newThreadPerTaskExecutor() else if (className.equals(CLASS_NAME_THREAD_PER_TASK_EXECUTOR)) { monitorThreadPerTaskExecutor(registry, executorService); } From c9420490c3e7efe0a43b18601324e8e320b2e328 Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Tue, 18 Mar 2025 15:11:29 +0900 Subject: [PATCH 2/2] Add Executors.newVirtualThreadPerTaskExecutor() to docs Signed-off-by: Johnny Lim --- docs/modules/ROOT/pages/reference/jvm.adoc | 1 + .../core/instrument/binder/jvm/ExecutorServiceMetrics.java | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/modules/ROOT/pages/reference/jvm.adoc b/docs/modules/ROOT/pages/reference/jvm.adoc index a19099ff1d..9ae5e91c05 100644 --- a/docs/modules/ROOT/pages/reference/jvm.adoc +++ b/docs/modules/ROOT/pages/reference/jvm.adoc @@ -50,6 +50,7 @@ To use the following `ExecutorService` instances, `--add-opens java.base/java.ut * `Executors.newSingleThreadScheduledExecutor()` * `Executors.newSingleThreadExecutor()` * `Executors.newThreadPerTaskExecutor()` +* `Executors.newVirtualThreadPerTaskExecutor()` == Java 21 Metrics diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java index de16b65d04..2c2e21ba83 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/ExecutorServiceMetrics.java @@ -57,6 +57,7 @@ *
  • Executors.newSingleThreadScheduledExecutor()
  • *
  • Executors.newSingleThreadExecutor()
  • *
  • Executors.newThreadPerTaskExecutor()
  • + *
  • Executors.newVirtualThreadPerTaskExecutor()
  • * * * @author Jon Schneider @@ -333,7 +334,8 @@ else if (className.equals("java.util.concurrent.Executors$FinalizableDelegatedEx monitor(registry, unwrapThreadPoolExecutor(executorService, executorService.getClass().getSuperclass())); } - // For Executors.newThreadPerTaskExecutor() + // For Executors.newThreadPerTaskExecutor() and + // Executors.newVirtualThreadPerTaskExecutor() else if (className.equals(CLASS_NAME_THREAD_PER_TASK_EXECUTOR)) { monitorThreadPerTaskExecutor(registry, executorService); }