Spring Data Redis是否支持GraalVM Native Image?配置后遇类初始化错误
Spring Boot 3 + GraalVM Native Image 下 Redis 连接错误排查与解决
问题描述
项目基于Spring Boot 3,在JVM环境下运行完全正常,但在Linux系统中使用GraalVM编译并运行时,出现如下错误:
java.lang.NoClassDefFoundError: Could not initialize class io.lettuce.core.event.connection.JfrConnectionCreatedEvent at java.base@17.0.7/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) at java.base@17.0.7/java.lang.reflect.Constructor.newInstance(Constructor.java:480) at io.lettuce.core.event.jfr.JfrEventRecorder.createEvent(JfrEventRecorder.java:108) at io.lettuce.core.event.jfr.JfrEventRecorder.record(JfrEventRecorder.java:48) at io.lettuce.core.AbstractRedisClient.initializeChannelAsync(AbstractRedisClient.java:398) at io.lettuce.core.RedisClient.connectStatefulAsync(RedisClient.java:325) at io.lettuce.core.RedisClient.connectStandaloneAsync(RedisClient.java:287) at io.lettuce.core.RedisClient.connect(RedisClient.java:216) at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:112) at java.base@17.0.7/java.util.Optional.orElseGet(Optional.java:364) at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:112) at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.lambda$getConnection$0(LettucePoolingConnectionProvider.java:93) at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:211) at io.lettuce.core.support.ConnectionPoolSupport$RedisPooledObjectFactory.create(ConnectionPoolSupport.java:201) at org.apache.commons.pool2.BasePooledObjectFactory.makeObject(BasePooledObjectFactory.java:70) at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:571) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:298) at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:223) at io.lettuce.core.support.ConnectionPoolSupport$1.borrowObject(ConnectionPoolSupport.java:122) at io.lettuce.core.support.ConnectionPoolSupport$1.borrowObject(ConnectionPoolSupport.java:117) at org.springframework.data.redis.connection.lettuce.LettucePoolingConnectionProvider.getConnection(LettucePoolingConnectionProvider.java:99) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1531) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1358) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1341) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:1059) at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getConnection(LettuceConnectionFactory.java:398) at org.springframework.data.redis.core.RedisConnectionUtils.fetchConnection(RedisConnectionUtils.java:193) at org.springframework.data.redis.core.RedisConnectionUtils.doGetConnection(RedisConnectionUtils.java:144) at org.springframework.data.redis.core.RedisConnectionUtils.getConnection(RedisConnectionUtils.java:105) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:393) at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:373) at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:97) at org.springframework.data.redis.core.DefaultValueOperations.get(DefaultValueOperations.java:50) at com.benfei.web.util.RedisUtil.get(RedisUtil.java:71) at com.benfei.web.socket.MessageJob.runAdmin(MessageJob.java:38) at java.base@17.0.7/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:96) at java.base@17.0.7/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) at java.base@17.0.7/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base@17.0.7/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) at java.base@17.0.7/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base@17.0.7/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base@17.0.7/java.lang.Thread.run(Thread.java:833) at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:807) at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:210)
异常特殊场景:未在/META-INF/native-image目录下生成配置文件时,Redis可正常使用;添加该配置文件后反而触发上述错误。同时疑问:Spring Data Redis是否支持GraalVM Native Image?
解答
兼容性说明
Spring Data Redis 完全支持GraalVM Native Image,问题根源在于Lettuce客户端的JFR(Java Flight Recorder)事件在Native Image环境下无法正常初始化,且自定义的Native Image配置文件可能覆盖了Spring Boot自动生成的兼容配置。
解决步骤
1. 禁用Lettuce的JFR事件支持
JFR事件在Native Image环境下通常非必需,直接关闭即可避免初始化错误:
- 通过配置文件(application.properties):
spring.data.redis.lettuce.jfr.enabled=false - 或者通过Java配置手动构建Lettuce客户端:
@Configuration public class RedisConfig { @Bean public LettuceConnectionFactory lettuceConnectionFactory(RedisProperties properties) { LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder() .disableJfr() // 禁用JFR事件 .build(); return new LettuceConnectionFactory(properties.getRedisConfiguration(), clientConfig); } }
2. 修复Native Image配置文件
如果手动维护/META-INF/native-image下的配置,需确保兼容Lettuce的Native运行需求:
- 优先删除自定义配置,改用Spring Boot自动生成:运行
./gradlew nativeCompile(Gradle)或./mvnw native:compile(Maven)时,Spring Boot会自动生成适配的Native Image配置。 - 若必须手动配置,可在
native-image.properties中添加以下规则:# 禁止JFR相关类的初始化 --initialize-at-run-time=io.lettuce.core.event.connection.JfrConnectionCreatedEvent --exclude-config=io.lettuce.core.event.jfr.*
3. 检查依赖与环境版本
- 确保Spring Boot 3使用的Lettuce版本≥6.2.0(Spring Boot 3默认依赖版本已满足此要求,若手动升级需确认)。
- 确认GraalVM版本为Spring Boot 3推荐的版本(如GraalVM 22.3+ for Java 17)。
内容的提问来源于stack exchange,提问作者chrischou
相关产品推荐
相关产品推荐

