Spring Boot 3升级后K8s Pod重启:Instant序列化异常求助
升级Spring Boot 3版本后,应用部署到K8s Pod中出现反复重启,抛出错误:
ExceptionHandlerExceptionResolver : Resolved
[org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: Failed making field 'java.time.Instant#seconds'
accessible; either increase its visibility or write a custom
TypeAdapter for its declaring type.
已编写InstantAdapter并尝试相关方案,但问题依旧。本地运行正常,仅K8s环境异常。
现有代码
InstantAdapter实现
public class InstantAdapter extends TypeAdapter<Instant> { @Override public void write(JsonWriter out, Instant value) throws IOException { out.value(value.getEpochSecond()); } @Override public Instant read(JsonReader in) throws IOException { long seconds = in.nextLong(); return Instant.ofEpochSecond(seconds); } }
Gson配置
public static String toJSon(Object obj) { return getGson().toJson(obj); } public static Gson getGson() { return getGsonBuilder().create(); } public static GsonBuilder getGsonBuilder() { return new GsonBuilder() .serializeNulls() .setDateFormat(Constants.DATE_FORMAT) .registerTypeAdapterFactory(new GsonBaseDTOTypeAdapterFactory()) .registerTypeAdapterFactory(new GsonNullableTypeAdapterFactory()) .registerTypeAdapterFactory(new GsonAtomicReferenceTypeAdapterFactory()) .registerTypeAdapter(ResponseEntity.class, new HttpStatusCodeInterfaceAdapter()) .registerTypeAdapter(Instant.class, new InstantAdapter()) .addSerializationExclusionStrategy(new GsonAnnotationExcludeSerializationStrategy()) .addDeserializationExclusionStrategy(new GsonAnnotationExcludeDeserializationStrategy()); }
1. 适配Spring Boot 3与Gson的版本兼容性
Spring Boot 3基于Jakarta EE,对Java模块系统的限制更严格,K8s环境的JVM可能启用了严格的模块访问规则,而本地开发环境通常会放宽限制。
- 若无需强制使用Gson,直接切换为Spring Boot默认的Jackson处理器:移除Gson相关依赖,Spring Boot 3原生支持Java 8时间类型的序列化/反序列化,无需额外配置。
- 必须使用Gson时,升级到
2.10.1及以上版本,该版本优化了对Java模块系统的兼容性。
2. 修正Gson的Instant适配器注册方式
原代码使用registerTypeAdapter,对于Java 8时间类型,推荐使用registerTypeHierarchyAdapter确保所有Instant类型(包括泛型、继承场景下的)都能被适配器处理:
// 替换原registerTypeAdapter(Instant.class, new InstantAdapter()) .registerTypeHierarchyAdapter(Instant.class, new InstantAdapter())
3. 检查K8s环境的JVM启动参数
K8s中的JVM可能配置了--illegal-access=deny参数,禁止反射访问私有字段,导致Gson fallback到反射时触发错误。
- 临时方案:调整JVM参数为
--illegal-access=permit,允许临时的反射访问。 - 彻底方案:确保自定义
InstantAdapter完全覆盖序列化/反序列化逻辑,避免Gson使用反射处理Instant字段。
4. 确保Gson实例是单例且全局生效
原getGson()方法每次调用都会创建新的Gson实例,可能导致部分场景未加载适配器。修改为懒加载单例:
private static volatile Gson gsonInstance; public static Gson getGson() { if (gsonInstance == null) { synchronized (YourUtilClass.class) { if (gsonInstance == null) { gsonInstance = getGsonBuilder().create(); } } } return gsonInstance; }
同时排查应用中是否存在其他未使用此单例的Gson实例创建代码。
5. 配置Spring MVC使用自定义Gson实例
若报错发生在Spring MVC返回响应时,需要确保Spring使用自定义的Gson实例处理JSON:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { GsonHttpMessageConverter gsonConverter = new GsonHttpMessageConverter(); gsonConverter.setGson(YourUtilClass.getGson()); converters.add(gsonConverter); } }
内容的提问来源于stack exchange,提问作者Eugen Gîrlescu

