【发布时间】:2021-12-06 09:37:57
【问题描述】:
由于使用 EntryExpiredListener 时未找到类,我收到了序列化异常。
我创建了一个测试 jar 并缩小了问题范围。
Test jar 包含 TestService、CacheKey 和 CacheValue。 TestService 将键类型 CacheKey 和值类型 CacheValue 插入到 IMap。 它注册了一个 EntryExpiryListener 来监听插入的条目是否过期。
TestService 代码很简单:
hazelcastService.put(
new CacheKey("11", "12345", "678910", 1624174140000L),
new CacheValue(new HashMap<>())); // ttl is set to 30 sec
Collection<HazelcastInstance> instances = HazelcastClient.getAllHazelcastClients();
Optional<HazelcastInstance> instance = instances.stream().findAny();
if (!instance.isPresent()) {
throw new IllegalStateException("Can not find Hazelcast instance!");
}
// HazelcastInstance is created by framework component
IMap<CacheKey, CacheValue> cacheMap = instance.get().getMap(cacheName);
cacheMap.addEntryListener((EntryExpiredListener<CacheKey, CacheValue>) event -> {
CacheKey key = event.getKey();
CacheValue val = event.getOldValue();
}, true);
public class CacheKey implements Serializable {
private static final long serialVersionUID = 123412453256L;
private final String type;
private final String field1;
private final String field2;
private final long timestamp;
// constructor, getters
public class CacheValue implements Serializable {
private static final long serialVersionUID = 658933453256L;
private final HashMap<String, Object> recordMap;
// constructor, getters
问题
entry 过期时,由于 CacheKey 的 class not found 异常而引发序列化异常。
Method threw 'com.hazelcast.nio.serialization.HazelcastSerializationException' exception. Cannot evaluate com.hazelcast.map.impl.DataAwareEntryEvent.toString()
2021-10-19 16:41:13,921 ERROR [hz.client_1.event-4] c.h.c.impl.spi.ClientListenerService hz.client_1 [nifi] [4.2] hz.client_1.event-4 caught an exception while processing:com.hazelcast.client.impl.spi.impl.listener.ClientListenerServiceImpl$ClientEventProcessor@782e8844
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: com.myapp.expirytest.CacheKey
at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:90)
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)
at com.hazelcast.map.impl.DataAwareEntryEvent.getKey(DataAwareEntryEvent.java:74)
at com.ipfli.drs.nifi.processor.hzexpirytest.ExpiryTest.lambda$onScheduled$0(ExpiryTest.java:112)
at com.hazelcast.map.impl.MapListenerAdaptors.lambda$null$6(MapListenerAdaptors.java:93)
at com.hazelcast.map.impl.InternalMapListenerAdapter.onEvent(InternalMapListenerAdapter.java:56)
at com.hazelcast.map.impl.InternalMapListenerAdapter.onEvent(InternalMapListenerAdapter.java:35)
at com.hazelcast.client.impl.proxy.ClientMapProxy$AbstractClientMapEventHandler.handleEntryEvent(ClientMapProxy.java:2004)
at com.hazelcast.client.impl.proxy.ClientMapProxy$ClientMapEventHandler$1.handleEntryEvent(ClientMapProxy.java:1981)
at com.hazelcast.client.impl.protocol.codec.MapAddEntryListenerCodec$AbstractEventHandler.handle(MapAddEntryListenerCodec.java:164)
at com.hazelcast.client.impl.proxy.ClientMapProxy$ClientMapEventHandler.handle(ClientMapProxy.java:1989)
at com.hazelcast.client.impl.proxy.ClientMapProxy$ClientMapEventHandler.handle(ClientMapProxy.java:1971)
at com.hazelcast.client.impl.spi.impl.listener.ClientListenerServiceImpl.handleEventMessageOnCallingThread(ClientListenerServiceImpl.java:189)
at com.hazelcast.client.impl.spi.impl.listener.ClientListenerServiceImpl$ClientEventProcessor.run(ClientListenerServiceImpl.java:356)
at com.hazelcast.internal.util.executor.StripedExecutor$Worker.process(StripedExecutor.java:245)
at com.hazelcast.internal.util.executor.StripedExecutor$Worker.run(StripedExecutor.java:228)
Caused by: java.lang.ClassNotFoundException: com.myapp.expirytest.CacheKey
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at com.hazelcast.internal.nio.ClassLoaderUtil.tryLoadClass(ClassLoaderUtil.java:289)
at com.hazelcast.internal.nio.ClassLoaderUtil.loadClass(ClassLoaderUtil.java:249)
at com.hazelcast.internal.nio.IOUtil$ClassLoaderAwareObjectInputStream.resolveClass(IOUtil.java:910)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1984)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2158)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1665)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:501)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:459)
at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:86)
... 17 common frames omitted
测试 jar 部署到 user-lib 文件夹。 我知道 CacheKey 类已正确部署在服务器端,因为我使用不同的服务来获取它,它可以正常工作。 做了很多其他的测试。唯一的问题是 EntryExpiredListener。
Hazelcast 服务器和 JVM 客户端都在我的本地机器上运行,单节点。 Hazelcast 4.2.1 版
所以一切都在同一个 jar 中,我知道类部署在服务器端。 我错过了什么?
【问题讨论】:
-
为什么要删除之前的问题?
-
我以为不会得到答案,这个版本更容易理解。不想复制东西。如果您有意见,我会取消删除它。
-
不要删除问题,编辑它们。而现在,你重复了????
-
我将不得不编辑整个内容,这等于重新创建它。如果我保留旧内容并发布更新,那么它只是一个令人困惑的混乱。我认为这是一个更加集中和缩小的版本。现在最好的处理方法是什么?
标签: java serialization deserialization hazelcast