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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:22:24