micronaut-cache
micronaut-cache copied to clipboard
Caffeine and Graal native-image
Task List
- [x] Steps to reproduce provided
- [x] Stacktrace (if present) provided
- [ ] Example that reproduces the problem uploaded to Github
- [x] Full description of the issue provided (see below)
Steps to Reproduce
- Include
<dependency>
<groupId>io.micronaut.cache</groupId>
<artifactId>micronaut-cache-caffeine</artifactId>
<scope>compile</scope>
</dependency>
- Add
<annotationProcessorPaths>
<path>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-graal</artifactId>
<version>${micronaut.version}</version>
</path>
</annotationProcessorPaths>
- Add method annotated with
@Cacheable
- run
./mvnw package -Dpackaging=native-image
- run binary
Expected Behaviour
It runs.
Actual Behaviour
Exception when accessing the cache:
Message: com.github.benmanes.caffeine.cache.SSW
Path Taken: new CacheHeater([CoolestProjectService service]) --> new $CoolestProjectServiceImplDefinition$Intercepted(GitHubClient client,BeanContext $beanContext,Qualifier $qualifier,[Interceptor[] $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager)
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type [io.micronaut.cache.DefaultCacheManager]
Message: com.github.benmanes.caffeine.cache.SSW
Path Taken: new CacheHeater([CoolestProjectService service]) --> new $CoolestProjectServiceImplDefinition$Intercepted(GitHubClient client,BeanContext $beanContext,Qualifier $qualifier,[Interceptor[] $interceptors]) --> new CacheInterceptor([CacheManager cacheManager],CacheErrorHandler errorHandler,AsyncCacheErrorHandler asyncCacheErrorHandler,ExecutorService ioExecutor,BeanContext beanContext) --> new DefaultCacheManager([List caches],Provider dynamicCacheManager)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1925)
at io.micronaut.context.DefaultBeanContext.addCandidateToList(DefaultBeanContext.java:3022)
at io.micronaut.context.DefaultBeanContext.getBeansOfTypeInternal(DefaultBeanContext.java:2923)
at io.micronaut.context.DefaultBeanContext.getBeansOfType(DefaultBeanContext.java:1045)
at io.micronaut.context.AbstractBeanDefinition.lambda$getBeansOfTypeForConstructorArgument$9(AbstractBeanDefinition.java:1143)
at io.micronaut.context.AbstractBeanDefinition.resolveBeanWithGenericsFromConstructorArgument(AbstractBeanDefinition.java:1822)
at io.micronaut.context.AbstractBeanDefinition.getBeansOfTypeForConstructorArgument(AbstractBeanDefinition.java:1138)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:990)
at io.micronaut.cache.$DefaultCacheManagerDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1898)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2679)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2665)
at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2337)
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2311)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1245)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1013)
at io.micronaut.cache.interceptor.$CacheInterceptorDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1898)
at io.micronaut.context.DefaultBeanContext.addCandidateToList(DefaultBeanContext.java:3022)
at io.micronaut.context.DefaultBeanContext.getBeansOfTypeInternal(DefaultBeanContext.java:2897)
at io.micronaut.context.DefaultBeanContext.getBeansOfType(DefaultBeanContext.java:1045)
at io.micronaut.context.AbstractBeanDefinition.lambda$getBeansOfTypeForConstructorArgument$9(AbstractBeanDefinition.java:1143)
at io.micronaut.context.AbstractBeanDefinition.resolveBeanWithGenericsFromConstructorArgument(AbstractBeanDefinition.java:1822)
at io.micronaut.context.AbstractBeanDefinition.getBeansOfTypeForConstructorArgument(AbstractBeanDefinition.java:1138)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:987)
at mn.demo.service.impl.$$CoolestProjectServiceImplDefinition$InterceptedDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1898)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2679)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2665)
at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2337)
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2311)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1245)
at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1013)
at mn.demo.$CacheHeaterDefinition.build(Unknown Source)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1898)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2679)
at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2665)
at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2337)
at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2311)
at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:721)
at io.micronaut.scheduling.processor.ScheduledMethodProcessor.lambda$process$5(ScheduledMethodProcessor.java:123)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.lang.Thread.run(Thread.java:834)
at com.oracle.svm.core.thread.JavaThreads.threadStartRoutine(JavaThreads.java:519)
at com.oracle.svm.core.posix.thread.PosixJavaThreads.pthreadStartRoutine(PosixJavaThreads.java:192)
Caused by: java.lang.IllegalStateException: com.github.benmanes.caffeine.cache.SSW
at com.github.benmanes.caffeine.cache.LocalCacheFactory.newBoundedLocalCache(LocalCacheFactory.java:95)
at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3353)
at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3349)
at com.github.benmanes.caffeine.cache.Caffeine.build(Caffeine.java:996)
at io.micronaut.cache.caffeine.DefaultSyncCache.buildCache(DefaultSyncCache.java:209)
at io.micronaut.cache.caffeine.DefaultSyncCache.<init>(DefaultSyncCache.java:90)
at io.micronaut.cache.caffeine.$DefaultSyncCacheDefinition.build(Unknown Source)
at io.micronaut.context.BeanDefinitionDelegate.build(BeanDefinitionDelegate.java:148)
at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1898)
... 48 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.github.benmanes.caffeine.cache.SSW
at com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:60)
at java.lang.Class.forName(DynamicHub.java:1247)
at com.github.benmanes.caffeine.cache.LocalCacheFactory.newBoundedLocalCache(LocalCacheFactory.java:87)
... 56 common frames omitted
Environment Information
-
Operating System:
Linux P1 5.10.10-200.fc33.x86_64 #1 SMP Sun Jan 24 19:58:54 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
- Micronaut Version: 2.3.0
-
JDK Version:
OpenJDK 64-Bit Server VM GraalVM CE 21.0.0 (build 11.0.10+8-jvmci-21.0-b06, mixed mode, sharing)
Similar issue in Quarkus: https://github.com/quarkusio/quarkus/issues/10420.
Looks like some additional reflect-config.json
entries will be needed for the Caffeine classes. @phxql, doe sthis as a workaround for you? https://github.com/quarkusio/quarkus/issues/10420#issuecomment-653021260
As per https://github.com/quarkusio/quarkus/issues/12961 we are in the same boat, we can't register all the different caffeine combinations because it would increase memory by a lot, users need to add the @TypeHint
definitions for each CNFE produced
In https://github.com/quarkusio/quarkus/issues/10420#issuecomment-654483795, @Sanne suggested an API to "warmup" with so that the AOT could determine which classes to include. I'm not sure how to implement this so if someone more familiar with Graal and how this might work wants to iterate with me, we can try to find a suitable factory construct.
I got it working with this config: https://github.com/qaware/microservices-with-micronaut/blob/master/github-scraper-graal/src/main/graal/reflect.json
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Here is a Kotlin solution with TypeHints. Maybe access types could be reduced, I added all of them for now.
@Context
@TypeHint(
typeNames = [
"com.github.benmanes.caffeine.cache.SSW",
"com.github.benmanes.caffeine.cache.SSMSW",
"com.github.benmanes.caffeine.cache.BLCHeader\$DrainStatusRef",
"com.github.benmanes.caffeine.cache.PSWMS",
"com.github.benmanes.caffeine.cache.PS",
"com.github.benmanes.caffeine.cache.PSW",
"com.github.benmanes.caffeine.cache.StripedBuffer",
"java.lang.Thread",
"com.github.benmanes.caffeine.cache.BBHeader\$ReadCounterRef",
"com.github.benmanes.caffeine.cache.BBHeader\$ReadAndWriteCounterRef",
], accessType = [
TypeHint.AccessType.ALL_DECLARED_CONSTRUCTORS,
TypeHint.AccessType.ALL_DECLARED_FIELDS,
TypeHint.AccessType.ALL_DECLARED_METHODS,
TypeHint.AccessType.ALL_PUBLIC,
TypeHint.AccessType.ALL_PUBLIC_CONSTRUCTORS,
TypeHint.AccessType.ALL_PUBLIC_FIELDS,
TypeHint.AccessType.ALL_PUBLIC_METHODS
]
)
class CaffeineGraalConfig()