You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:15:54