给实体加了个字段后重新发布,读 Redis 里的老会话直接报 InvalidClassException: local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 3654821。碰到这种情况,我一般先确认改动有没有真的生效。

原因不复杂,JDK 序列化会把 serialVersionUID 写进字节流,读的时候和本地类比对,不一致就拒绝。没显式声明时由编译器按字段和方法签名算出来,加字段就会变。

碰到「Java 序列化版本号」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。别只看报错的最后一行,往上看几行,真正的起因通常在上面。

private static final long serialVersionUID = 1L;
// 增减字段时保持这个值不变

同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。把这次用到的命令存进笔记,比记住结论有用,换个环境还能照着走。

具体做法是,给所有要序列化的类显式写死 serialVersionUID;兼容期保留旧字段 不要直接删 删了也会改变计算结果;新老结构差异大的字段用 transient 跳过;清掉旧缓存前先确认线上没有实例还在读。

最后用这个标准收尾,同一个 key 的旧数据能被新代码读出 不再抛 InvalidClassException。

作者 9823189