【发布时间】:2021-03-11 08:51:17
【问题描述】:
考虑以下代码 sn-p 以从 Hazelcast 获取/提交 Collections.synchronizedSet:
IMap imap = getIMapFromHazelcastClient();
Set<UUID> mySet = (Set<UUID>)imap.get("someKey"); //This may trigger a stackOverflow, see below.
if ( mySet == null ){
mySet = Collections.synchronizedSet(new HashSet<UUID>());
}else{
mySet = Collections.synchronizedSet(mySet);
}
//Concurrently add/remove elements from mySet
//After all concurrent operations complete, store the updated Set to Hazelcast.
//mySet should contain about 1-1.5K UUIDs at this point, every time.
imap.set("someKey", mySet);
在这段代码运行了几次之后(不知道有多少次,或者为什么),在尝试从 Hazelcast 获取 Set 时触发了以下代码(上面标记):
java.lang.StackOverflowError
at java.base/java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2914)
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2930)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(ObjectInputStream.java:3439)
at java.base/java.io.ObjectInputStream$BlockDataInputStream.readUTF(ObjectInputStream.java:3497)
at java.base/java.io.ObjectInputStream.readUTF(ObjectInputStream.java:1242)
at java.base/java.io.ObjectStreamClass.readNonProxy(ObjectStreamClass.java:800)
at java.base/java.io.ObjectInputStream.readClassDescriptor(ObjectInputStream.java:991)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2017)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1895)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2202)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477)
at java.base/java.util.HashSet.readObject(HashSet.java:344)
at java.base/jdk.internal.reflect.GeneratedMethodAccessor564.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1226)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2401)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
...About 900 lines of these
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2540)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2434)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2540)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2434)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2540)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2434)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2235)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1712)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:519)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:477)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:84)
at com.hazelcast.internal.serialization.impl.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:77)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:48)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:187)
at com.hazelcast.client.spi.ClientProxy.toObject(ClientProxy.java:102)
at com.hazelcast.client.proxy.ClientMapProxy.get(ClientMapProxy.java:318)
...
如果相关,应用程序和 Hazelcast (v3.12.9) 在相同的 JVM 版本上运行:OpenJDK 运行时环境(内部版本 15.0.1+9-18)和相同的硬件上。当 Hazelcast 在 v1.8.0 JVM 上运行时观察到相同的行为。
在存储部分用一个简单的 HashSet 替换 synchronizedSet 后,问题似乎解决了:
imap.set("someKey", new HashSet(mySet));
显然,在 Hazelcast 中存储 synchronizedSet 没有任何意义,但是 stackoverflow 是否合理?我错过了什么吗?
【问题讨论】:
标签: java serialization deserialization stack-overflow hazelcast