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

同一类出现ClassCastException异常排查(Spring Boot DevTools场景)

同一类出现ClassCastException的原因与解决方法

从报错日志能看到核心问题:

Caused by: java.lang.ClassCastException: class com.exceltic.commons.api.model.datacollector.accounts.CompletedAccountDTO cannot be cast to class com.exceltic.commons.api.model.datacollector.accounts.CompletedAccountDTO (com.exceltic.commons.api.model.datacollector.accounts.CompletedAccountDTO is in unnamed module of loader 'app'; com.exceltic.commons.api.model.datacollector.accounts.CompletedAccountDTO is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @2db52090)

Java里判断两个类是否为同一类型,不仅看全限定类名,还要看加载它的类加载器。这里CompletedAccountDTO被两个不同的类加载器加载了:一个是系统类加载器('app' loader),另一个是Spring Boot DevTools的RestartClassLoader,所以它们在JVM里是完全不同的类型,哪怕名字完全一样,哪怕是隐式的类型转换(比如映射框架内部的转换)都会抛出ClassCastException。

为什么会触发这个问题?

你用了Spring Boot DevTools的热重启功能,它的RestartClassLoader会单独加载应用代码,实现修改代码后快速重启。但Kafka的反序列化过程可能用了系统类加载器加载CompletedAccountDTO,而你的DTO与实体映射逻辑(比如AccountsMapperImpl里的代码)是被RestartClassLoader加载的,这就导致两个类实例属于不同类加载器下的类型,映射时触发类型转换异常。

解决方法

  • 排除DTO包到DevTools重启范围外:在application.properties或application.yml里添加配置,让DTO类始终由系统类加载器加载:
    spring.devtools.restart.exclude=com/exceltic/commons/api/model/datacollector/accounts/**
    
  • 禁用DevTools热重启:如果不需要热重启功能,直接关闭它,在配置文件里设置:
    spring.devtools.restart.enabled=false
    
    或者移除pom.xml(或build.gradle)里的DevTools依赖。
  • 统一类加载器:自定义Kafka反序列化器,使用当前线程的上下文类加载器加载CompletedAccountDTO,确保和映射逻辑用同一个类加载器。示例代码如下:
    public class CustomDeserializer implements Deserializer<CompletedAccountDTO> {
        @Override
        public CompletedAccountDTO deserialize(String topic, byte[] data) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                return objectMapper.readValue(data, classLoader.loadClass("com.exceltic.commons.api.model.datacollector.accounts.CompletedAccountDTO"));
            } catch (IOException | ClassNotFoundException e) {
                throw new SerializationException("Failed to deserialize CompletedAccountDTO", e);
            }
        }
    }
    
    然后在Kafka消费者配置里指定这个自定义反序列化器。

内容的提问来源于stack exchange,提问作者Miguel Ángel Cantarero Ortega

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:25:11