diff --git a/extensions/caffeine/deployment/src/main/java/io/quarkus/caffeine/deployment/CaffeineProcessor.java b/extensions/caffeine/deployment/src/main/java/io/quarkus/caffeine/deployment/CaffeineProcessor.java
index 362742fff2d4b8..0493b452a6acb8 100644
--- a/extensions/caffeine/deployment/src/main/java/io/quarkus/caffeine/deployment/CaffeineProcessor.java
+++ b/extensions/caffeine/deployment/src/main/java/io/quarkus/caffeine/deployment/CaffeineProcessor.java
@@ -7,13 +7,13 @@
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
-import io.quarkus.caffeine.runtime.graal.CacheConstructorsFeature;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
-import io.quarkus.deployment.builditem.NativeImageFeatureBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
import io.quarkus.deployment.pkg.steps.NativeOrNativeSourcesBuild;
+import io.quarkus.runtime.metrics.MetricsFactory;
public class CaffeineProcessor {
@@ -26,6 +26,45 @@ public class CaffeineProcessor {
private static final DotName CACHE_LOADER_NAME = DotName.createSimple(CACHE_LOADER_CLASS_NAME);
+ /**
+ * this list is not complete, but a selection of the types we expect being most useful.
+ * unfortunately registering all of them has been shown to have a very significant impact
+ * on executable sizes. See https://github.com/quarkusio/quarkus/issues/12961
+ */
+ private static final String[] DEFAULT_CACHE_IMPLEMENTATIONS_TO_REGISTER_FOR_REFLECTION = {
+ "com.github.benmanes.caffeine.cache.PDMS",
+ "com.github.benmanes.caffeine.cache.PSA",
+ "com.github.benmanes.caffeine.cache.PSMS",
+ "com.github.benmanes.caffeine.cache.PSW",
+ "com.github.benmanes.caffeine.cache.PSMW",
+ "com.github.benmanes.caffeine.cache.PSWMS",
+ "com.github.benmanes.caffeine.cache.PSWMW",
+ "com.github.benmanes.caffeine.cache.SILMS",
+ "com.github.benmanes.caffeine.cache.SSA",
+ "com.github.benmanes.caffeine.cache.SSLA",
+ "com.github.benmanes.caffeine.cache.SSLMS",
+ "com.github.benmanes.caffeine.cache.SSMS",
+ "com.github.benmanes.caffeine.cache.SSMSA",
+ "com.github.benmanes.caffeine.cache.SSMSW",
+ "com.github.benmanes.caffeine.cache.SSW"
+ };
+
+ /**
+ * When the Micrometer extension is around, we add the cache classes with metrics.
+ *
+ * Note that we don't know if they will actually be used given the cache configuration is defined at runtime.
+ */
+ private static final String[] METRICS_CACHE_IMPLEMENTATIONS_TO_REGISTER_FOR_REFLECTION = {
+ "com.github.benmanes.caffeine.cache.SILSMS",
+ "com.github.benmanes.caffeine.cache.SSSA",
+ "com.github.benmanes.caffeine.cache.SSLSA",
+ "com.github.benmanes.caffeine.cache.SSLSMS",
+ "com.github.benmanes.caffeine.cache.SSSMS",
+ "com.github.benmanes.caffeine.cache.SSSMSA",
+ "com.github.benmanes.caffeine.cache.SSSMSW",
+ "com.github.benmanes.caffeine.cache.SSSW"
+ };
+
@BuildStep
void cacheLoaders(CombinedIndexBuildItem combinedIndex, BuildProducer reflectiveClasses) {
final Collection implementors = combinedIndex.getIndex().getAllKnownImplementors(CACHE_LOADER_NAME);
@@ -46,7 +85,14 @@ void cacheLoaders(CombinedIndexBuildItem combinedIndex, BuildProducer reflectiveClasses) {
+ reflectiveClasses
+ .produce(new ReflectiveClassBuildItem(false, false, DEFAULT_CACHE_IMPLEMENTATIONS_TO_REGISTER_FOR_REFLECTION));
+
+ if (metricsCapability.metricsSupported(MetricsFactory.MICROMETER)) {
+ reflectiveClasses
+ .produce(new ReflectiveClassBuildItem(false, false,
+ METRICS_CACHE_IMPLEMENTATIONS_TO_REGISTER_FOR_REFLECTION));
+ }
}
}
diff --git a/extensions/caffeine/runtime/src/main/java/io/quarkus/caffeine/runtime/graal/CacheConstructorsFeature.java b/extensions/caffeine/runtime/src/main/java/io/quarkus/caffeine/runtime/graal/CacheConstructorsFeature.java
deleted file mode 100644
index 599100d1aad72c..00000000000000
--- a/extensions/caffeine/runtime/src/main/java/io/quarkus/caffeine/runtime/graal/CacheConstructorsFeature.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package io.quarkus.caffeine.runtime.graal;
-
-import java.lang.reflect.Constructor;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.graalvm.nativeimage.hosted.Feature;
-import org.graalvm.nativeimage.hosted.RuntimeReflection;
-
-/**
- * This Automatic Feature for GraalVM will register for reflection
- * the most commonly used cache implementations from Caffeine.
- * It's implemented as an explicit @{@link Feature} rather than
- * using the Quarkus builditems because it doesn't need to be
- * dynamically tuned (the list is static), and to take advantage
- * of the reachability information we can infer from @{@link org.graalvm.nativeimage.hosted.Feature.DuringAnalysisAccess}.
- *
- * This allows us to register for reflection these resources only if
- * Caffeine is indeed being used: only if the cache builder is reachable
- * in the application code.
- */
-public class CacheConstructorsFeature implements Feature {
-
- private final AtomicBoolean triggered = new AtomicBoolean(false);
-
- /**
- * To set this, add `-J-Dio.quarkus.caffeine.graalvm.diagnostics=true` to the native-image parameters
- */
- private static final boolean log = Boolean.getBoolean("io.quarkus.caffeine.graalvm.diagnostics");
-
- @Override
- public void beforeAnalysis(BeforeAnalysisAccess access) {
- Class> caffeineCoreClazz = access.findClassByName("com.github.benmanes.caffeine.cache.Caffeine");
- access.registerReachabilityHandler(this::ensureCaffeineSupportEnabled, caffeineCoreClazz);
- }
-
- private void ensureCaffeineSupportEnabled(DuringAnalysisAccess duringAnalysisAccess) {
- final boolean needsEnablingYet = triggered.compareAndSet(false, true);
- if (needsEnablingYet) {
- if (log) {
- System.out.println(
- "Quarkus's automatic feature for GraalVM native images: enabling support for core Caffeine caches");
- }
- registerCaffeineReflections(duringAnalysisAccess);
- }
- }
-
- private void registerCaffeineReflections(DuringAnalysisAccess duringAnalysisAccess) {
- final String[] needsHavingSimpleConstructors = typesNeedingConstructorsRegistered();
- for (String className : needsHavingSimpleConstructors) {
- registerForReflection(className, duringAnalysisAccess);
- }
- }
-
- private void registerForReflection(
- String className,
- DuringAnalysisAccess duringAnalysisAccess) {
- final Class> aClass = duringAnalysisAccess.findClassByName(className);
- final Constructor>[] z = aClass.getDeclaredConstructors();
- RuntimeReflection.register(aClass);
- RuntimeReflection.register(z);
- }
-
- public static String[] typesNeedingConstructorsRegistered() {
- return new String[] {
- //N.B. this list is not complete, but a selection of the types we expect being most useful.
- //unfortunately registering all of them has been shown to have a very significant impact
- //on executable sizes. See https://github.com/quarkusio/quarkus/issues/12961
- "com.github.benmanes.caffeine.cache.PDMS",
- "com.github.benmanes.caffeine.cache.PSA",
- "com.github.benmanes.caffeine.cache.PSMS",
- "com.github.benmanes.caffeine.cache.PSW",
- "com.github.benmanes.caffeine.cache.PSWMS",
- "com.github.benmanes.caffeine.cache.PSWMW",
- "com.github.benmanes.caffeine.cache.SILMS",
- "com.github.benmanes.caffeine.cache.SSA",
- "com.github.benmanes.caffeine.cache.SSLA",
- "com.github.benmanes.caffeine.cache.SSLMS",
- "com.github.benmanes.caffeine.cache.SSMS",
- "com.github.benmanes.caffeine.cache.SSMSA",
- "com.github.benmanes.caffeine.cache.SSMSW",
- "com.github.benmanes.caffeine.cache.SSW",
- };
- }
-
-}
diff --git a/integration-tests/cache/src/main/resources/application.properties b/integration-tests/cache/src/main/resources/application.properties
index 4e01418c2e2ada..b94edbb9836783 100644
--- a/integration-tests/cache/src/main/resources/application.properties
+++ b/integration-tests/cache/src/main/resources/application.properties
@@ -5,6 +5,8 @@ quarkus.hibernate-orm.sql-load-script=import.sql
# configure the caches
quarkus.cache.caffeine."forest".expire-after-write=10M
+
+quarkus.cache.caffeine."expensiveResourceCache".expire-after-write=10M
quarkus.cache.caffeine."expensiveResourceCache".metrics-enabled=true
io.quarkus.it.cache.SunriseRestClient/mp-rest/url=${test.url}