使用GraalVM原生镜像运行Java17-SpringBoot3-Ehcache项目报错
Ehcache + GraalVM原生镜像启动失败:序列化器构造器异常
环境与配置
- JDK版本:Java 17
- Spring Boot版本:3.x
- 缓存方案:Spring Boot Cache + Ehcache 3.10.8
- 构建方式:GraalVM原生镜像,通过Docker Compose构建运行
Maven依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.10.8</version> </dependency>
Ehcache配置类
import java.time.Duration; import javax.cache.CacheManager; import javax.cache.Caching; import org.ehcache.config.builders.CacheConfigurationBuilder; import org.ehcache.config.builders.ExpiryPolicyBuilder; import org.ehcache.config.builders.ResourcePoolsBuilder; import org.ehcache.config.units.MemoryUnit; import org.ehcache.jsr107.Eh107Configuration; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @EnableCaching @Configuration public class EhcacheConfiguration { @Bean public CacheManager EhcacheManager() { var cachingProvider = Caching.getCachingProvider(); var cacheManager = cachingProvider.getCacheManager(); cacheManager.createCache("myTestOne", Eh107Configuration.fromEhcacheCacheConfiguration( CacheConfigurationBuilder .newCacheConfigurationBuilder(Integer.class, MyObject.class, ResourcePoolsBuilder.newResourcePoolsBuilder() .offheap(100, MemoryUnit.MB) .build()) .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofHours(23))) .build() ) ); return cacheManager; } }
Spring Native插件配置
<plugin> <groupId>org.graalvm.buildtools</groupId> <artifactId>native-maven-plugin</artifactId> <executions> <execution> <id>build-native</id> <goals> <goal>compile-no-fork</goal> </goals> <phase>package</phase> </execution> </executions> </plugin>
Docker相关配置
Dockerfile
FROM ghcr.io/graalvm/graalvm-ce:ol7-java17-22.3.0 as build RUN gu install native-image RUN yum install -y zip unzip libstdc++-static freetype-devel WORKDIR /app COPY mvnw . COPY .mvn .mvn COPY pom.xml . RUN chmod +x ./mvnw COPY src src RUN ./mvnw clean package -DskipTests -Pnative ENTRYPOINT ["sh", "-c" ,"./target/test-app-one"]
docker-compose.yml
services: app-server: build: context: . dockerfile: Dockerfile ports: - "8080:8080" restart: always
问题现象
执行docker-compose up --build后,镜像构建成功,但应用启动失败,核心报错:
Caused by: java.lang.IllegalArgumentException: The serializer: org.ehcache.impl.serialization.PlainJavaSerializer does not have a constructor that takes in a ClassLoader.
非原生镜像运行正常,移除缓存依赖后原生镜像也能正常启动。
解决方案
原因分析
GraalVM原生镜像环境下,Ehcache默认使用的PlainJavaSerializer不满足序列化器的构造器要求——需要提供一个接收ClassLoader的构造方法,而原生镜像的类加载机制与标准JVM不同,导致该序列化器无法正常初始化。
修复步骤
- 显式指定兼容原生镜像的序列化器
为缓存配置添加自定义序列化器,使用Ehcache的DefaultSerializer(也可自行实现序列化器,确保包含ClassLoader参数的构造方法)。修改Ehcache配置类:
import org.ehcache.impl.serialization.DefaultSerializer; // ... 其他导入 @Bean public CacheManager EhcacheManager() { var cachingProvider = Caching.getCachingProvider(); var cacheManager = cachingProvider.getCacheManager(); // 配置键和值的序列化器 var cacheConfig = CacheConfigurationBuilder .newCacheConfigurationBuilder(Integer.class, MyObject.class, ResourcePoolsBuilder.newResourcePoolsBuilder().offheap(100, MemoryUnit.MB)) .withExpiry(ExpiryPolicyBuilder.timeToIdleExpiration(Duration.ofHours(23))) // 显式指定序列化器 .withKeySerializer(new DefaultSerializer<>(Integer.class)) .withValueSerializer(new DefaultSerializer<>(MyObject.class)) .build(); cacheManager.createCache("myTestOne", Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfig)); return cacheManager; }
添加GraalVM原生镜像元数据支持
Spring Boot 3.x结合GraalVM时,需确保Ehcache相关类被正确处理:- 添加
spring-boot-starter-aot依赖,自动生成原生镜像所需配置:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aot</artifactId> <scope>runtime</scope> </dependency>- 若自动生成不充分,手动创建
resources/META-INF/native-image/reflect-config.json,补充反射规则:
[ { "name": "org.ehcache.impl.serialization.DefaultSerializer", "constructors": [ { "parameters": ["java.lang.Class", "java.lang.ClassLoader"] } ] }, { "name": "com.test.testappone.MyObject", "allDeclaredConstructors": true, "allDeclaredFields": true, "allDeclaredMethods": true } ]- 添加
升级Ehcache版本(可选)
升级Ehcache到3.12+等最新稳定版,新版本对GraalVM原生镜像兼容性更好,可减少手动配置需求。验证构建与启动
重新执行docker-compose up --build,确认应用正常启动且缓存功能可用。
内容的提问来源于stack exchange,提问作者John Dillard
相关产品推荐
相关产品推荐

