GraalVM容器中Spring Boot应用java.lang.Integer序列化报错排查
问题描述
将Spring Boot应用部署至Docker容器中的GraalVM环境时,手动维护reflection-config.json和serialization-config.json配置文件过程中,遇到java.lang.Number、Integer、Boolean等基础Java核心类的序列化问题。
报错信息
2024-12-05T08:07:38.062Z ERROR 1 --- [wfprev] [nio-8080-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/wfprev-api] threw exception [Handler dispatch failed: com.oracle.svm.core.jdk.UnsupportedFeatureError: SerializationConstructorAccessor class not found for declaringClass: java.lang.Integer (targetConstructorClass: java.lang.Object). Usually adding java.lang.Integer to serialization-config.json fixes the problem.]
根因提示:
com.oracle.svm.core.jdk.UnsupportedFeatureError: SerializationConstructorAccessor class not found for declaringClass: java.lang.Integer (targetConstructorClass: java.lang.Object). Usually adding java.lang.Integer to serialization-config.json fixes the problem.
疑问:难道需要把所有Java类都添加到这些配置文件里吗?我哪里操作错了?
当前serialization-config.json配置
[ { "name": "org.springframework.hateoas.RepresentationModel"}, { "name": "org.springframework.hateoas.Link"}, { "name": "org.springframework.hateoas.Links"}, { "name": "java.util.Date"}, { "name": "java.sql.Timestamp" }, { "name": "java.lang.Number" }, { "name": "java.lang.Integer" }, { "name": "java.lang.Boolean" }, { "name": "java.math.BigDecimal" } ]
Dockerfile参考
FROM ghcr.io/graalvm/graalvm-community:21 AS builder # Define build argument and set it as environment variable ARG MAVEN_SETTINGS_FILE=settings.xml ENV MAVEN_SETTINGS_FILE=${MAVEN_SETTINGS_FILE} # The environment variables from .env are automatically available here # We don't need the ARG declarations anymore since we're using the env file WORKDIR /app # Copy maven settings first COPY mvn_settings/${MAVEN_SETTINGS_FILE} /root/.m2/settings.xml # Copy rest of the application COPY . /app # Make mvnw executable RUN chmod +x mvnw # Build the native image using settings.xml RUN ./mvnw -s mvn_settings/${MAVEN_SETTINGS_FILE} -Pnative native:compile -DskipTests # Runtime stage FROM ubuntu:22.04 # Install curl for healthcheck and debugging RUN apt-get update && apt-get install -y \ libc6 \ libstdc++6 \ curl \ && rm -rf /var/lib/apt/lists/* # Copy the native executable from builder stage COPY --from=builder /app/target/wfprev-api / # Expose the port your application uses EXPOSE 8080 ENTRYPOINT ["/wfprev-api"]
解决方案
1. 放弃手动维护配置,用GraalVM自动生成
你不需要手动添加这些基础Java类,核心问题是手动维护配置的方式效率低且容易遗漏关键信息。GraalVM提供了跟踪代理工具,能精准捕获应用运行时需要的反射、序列化类及相关细节:
- 以普通JVM模式启动应用,添加代理参数:
java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image -jar target/wfprev-api.jar - 触发所有涉及序列化/反射的业务操作(比如调用用到Integer、Boolean的接口),代理会自动生成完整的
reflection-config.json、serialization-config.json等配置文件到指定目录。 - 用自动生成的配置替换手动编写的版本,再重新构建Native Image。
2. 确保Spring Boot版本适配
使用Spring Boot 3.x及以上版本,该版本对GraalVM Native Image的支持更完善,很多序列化、反射的配置会由框架自动处理,无需手动干预。
3. 检查Native构建插件配置
在pom.xml中确保Spring Boot Native插件配置正确,插件会自动整合Spring的Native配置规则:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <native> <buildArgs>--no-fallback</buildArgs> </native> </configuration> </plugin>
4. 手动配置无效的原因
基础Java类的序列化在GraalVM中有特殊处理逻辑,仅添加类名的手动配置无法满足要求——自动生成的配置会包含构造函数、字段序列化等关键细节,这是手动配置缺失的内容。
内容的提问来源于stack exchange,提问作者The Funky Hermit
相关产品推荐
相关产品推荐

