启动Spring Boot应用时遭遇HazelcastSerializationException的解决咨询
异常日志
2024-06-10 07:00:24,459 WARNING [catalina] [com.hazelcast.spi.impl.proxyservice.ProxyService] [10.6.7.136]:5701 [nev-viewer-nev-2021-cluster] [4.2] Error while initializing proxy: IMap{name='spring:session:sessions'} com.hazelcast.nio.serialization.HazelcastSerializationException: java.io.InvalidClassException: org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; local class incompatible: stream classdesc serialVersionUID = 520, local class serialVersionUID = 570 2024-06-10 07:00:24,460 SEVERE [catalina] [com.hazelcast.spi.impl.proxyservice.impl.operations.PostJoinProxyOperation] [10.6.7.136]:5701 [nev-viewer-nev-2021-cluster] [4.2] Cannot create proxy [hz:impl:mapService:spring:session:sessions]! com.hazelcast.nio.serialization.HazelcastSerializationException: java.io.InvalidClassException: org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; local class incompatible: stream classdesc serialVersionUID = 520, local class serialVersionUID = 570 at com.hazelcast.internal.serialization.impl.SerializationUtil.handleException(SerializationUtil.java:103) at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:214) at com.hazelcast.map.impl.record.Records.tryStoreIntoCache(Records.java:203) at com.hazelcast.map.impl.record.Records.getValueOrCachedValue(Records.java:170) at com.hazelcast.map.impl.operation.AddIndexOperation.lambda$runInternal$0(AddIndexOperation.java:102) at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:278) at com.hazelcast.map.impl.recordstore.DefaultRecordStore.forEach(DefaultRecordStore.java:261) at com.hazelcast.map.impl.operation.AddIndexOperation.runInternal(AddIndexOperation.java:101) at com.hazelcast.map.impl.operation.MapOperation.run(MapOperation.java:115) at com.hazelcast.spi.impl.operationservice.Operation.call(Operation.java:189) at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.call(OperationRunnerImpl.java:272) at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:248) at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:469) at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:197) at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.process(OperationThread.java:137) at com.hazelcast.spi.impl.operationexecutor.impl.OperationThread.executeRun(OperationThread.java:123) at com.hazelcast.internal.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:102) Caused by: java.io.InvalidClassException: org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; local class incompatible: stream classdesc serialVersionUID = 520, local class serialVersionUID = 570 at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689) at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2012) at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1862) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2169) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451) at java.base/java.util.HashMap.readObject(HashMap.java:1460) at java.base/jdk.internal.reflect.GeneratedMethodAccessor136.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1175) at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2325) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2196) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679) at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2464) at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2358) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2196) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1679) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:493) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:451) at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:86) at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:79) at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44) at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:208) ... 15 more
场景说明
运行带有嵌入式Hazelcast(版本4.2)的Spring Boot应用时触发该异常,场景为基于现有Spring Boot服务Docker镜像,添加Hazelcast配置类进行自定义。已确认Spring Session Core依赖版本与镜像中版本兼容,需从OAuth2AuthorizationRequest角度排查解决方向。
统一Spring Security OAuth2依赖版本
异常核心是OAuth2AuthorizationRequest类的serialVersionUID不匹配,说明集群节点或本地应用与Hazelcast存储的数据使用的类版本不一致。需:- 核对Docker镜像内与自定义配置后引入的Spring Security OAuth2相关依赖版本是否完全一致;
- 确保集群所有节点的该类依赖版本统一,禁止混合版本部署。
清理Hazelcast持久化数据
若Hazelcast开启持久化(如MapStore、Hot Restart),旧版本序列化的数据无法被新版本反序列化。需:- 停止所有集群节点;
- 删除Hazelcast持久化目录下的全部数据;
- 重启集群节点。
排查依赖传递冲突
即使显式声明版本,也可能通过其他依赖(如Spring Boot Starter、第三方组件)引入不同版本的OAuth2AuthorizationRequest。可通过以下命令分析依赖树:# Maven项目 mvn dependency:tree | grep oauth2 # Gradle项目 ./gradlew dependencies | grep oauth2找到冲突依赖后,通过依赖排除或强制版本的方式解决。
自定义Hazelcast序列化器
若无法统一版本(不推荐),可为OAuth2AuthorizationRequest实现自定义序列化器,绕过Java默认序列化的serialVersionUID校验。实现StreamSerializer<OAuth2AuthorizationRequest>接口并注册到Hazelcast配置,用自定义逻辑完成序列化与反序列化。验证Spring Boot版本兼容性
Spring Boot与Spring Security OAuth2、Hazelcast存在兼容性矩阵,需确认当前Spring Boot版本是否同时兼容Hazelcast 4.2及使用的Spring Security OAuth2版本,避免因Spring Boot自动升级依赖导致版本不一致。
内容的提问来源于stack exchange,提问作者John Cooper

