Java RMI服务调用返回DTO时出现同全限定名ClassCastException问题求解
问题产生原因
你遇到的异常本质是类加载器隔离冲突,具体逻辑如下:
- JVM判定两个类是否为同一类的规则是「全限定类名+加载该类的类加载器」均一致。异常栈明确显示两个
hu.teszt.FileDto分别由app系统类加载器、Spring Boot Devtools自带的RestartClassLoader加载,即使类的全限定名完全相同,也会被判定为不同类,因此抛出类型转换异常。 - 冲突由Spring Boot Devtools的热重启机制触发:Devtools为实现快速热部署,会使用自定义的
RestartClassLoader加载项目内的业务代码,而RMI反序列化远程返回对象时默认使用系统类加载器加载序列化DTO类,最终导致两个相同全限定名的FileDto由不同类加载器加载,转换失败。 - 你尝试让DTO实现
java.rmi.Remote接口没有效果,因为问题核心并非RMI序列化规则不满足,而是本地类加载器的隔离冲突。
解决方案
提供三种适配不同场景的处理方式:
方案1:临时禁用Spring Boot Devtools(开发调试阶段快速验证用)
在项目的application.properties/application.yml配置文件中添加如下配置:spring.devtools.restart.enabled=false也可以在项目启动时添加JVM启动参数:
-Dspring.devtools.restart.enabled=false,重启项目后冲突即可消失。方案2:配置Devtools类加载白名单(保留热重启能力的最优解)
在项目resources目录下新建META-INF/spring-devtools.properties文件,添加配置将DTO所在包加入重启类加载器的排除列表,让该路径下的类统一由系统类加载器加载:spring.devtools.restart.exclude=hu/teszt/**该方案不会影响其他业务代码的热重启能力,适合开发阶段长期使用。
方案3:生产环境移除Devtools依赖
Spring Boot Devtools是开发阶段专用工具,正式发布时默认不会被打入依赖包。如果生产环境出现该问题,检查依赖配置,将Devtools的依赖scope设置为runtimeOnly或optional,避免其被打入正式发布的jar包即可。
内容的提问来源于stack exchange,提问作者István D
相关产品推荐
相关产品推荐

