为什么 apache ignite 没有反序列化 java.util.Collections$SetFromMap?
Why apache ignite is not deserializing the java.util.Collections$SetFromMap?
当我尝试将数据放入缓存时,Apache ignite 抛出以下异常,
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: [clsLdr=org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager$CacheClassLoader@5d5b5fa7, err=Failed to deserialize object [typeName=java.util.Collections$SetFromMap]]
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readSerializable(OptimizedObjectInputStream.java:608)
... 43 more
Caused by: java.lang.ClassNotFoundException: com.example.springapachecache.HelloWorld
计划:
package com.example.springapachecache;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
import java.util.*;
public class HelloWorld {
public static void main(String[] args) throws IgniteException {
// Preparing IgniteConfiguration using Java APIs
IgniteConfiguration cfg = new IgniteConfiguration();
// The node will be started as a client node.
cfg.setClientMode(true);
// Classes of custom Java logic will be transferred over the wire from this app.
cfg.setPeerClassLoadingEnabled(true);
// Setting up an IP Finder to ensure the client can locate the servers.
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"));
cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder));
// Starting the node
Ignite ignite = Ignition.start(cfg);
IgniteCache<Integer, Set<String>> setCache = ignite.getOrCreateCache("mySetCache");
System.out.println("setCache before: "+setCache.get(1));
Set<String> meetingUuids = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>() {
// Set backed by LRU map.
private static final long serialVersionUID = -8251614405342939979L;
@Override
protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) {
return size() > 1000;
}
});
meetingUuids.add("meetingId");
// Set<String> meetingUuidSet = new HashSet<>(meetingUuids);
// setCache.put(3, meetingUuidSet);
setCache.put(1, meetingUuids);
System.out.println("setCache after: "+setCache.get(1));
// Disconnect from the cluster.
ignite.close();
}
}
使用简单的 linkedHashMap(Set meetingUuids = Collections.newSetFromMap(new LinkedHashMap()) 构建 Set 效果很好。
你能帮忙吗?
您在最后一段中暗示了问题。您可以在 Ignite 中存储 Sets,并且可以通过网络“对等 class 加载”代码。您不能 做的是对等class 加载“模型”中使用的代码,即用于定义缓存的任何class。在您的示例代码中,这是 Collections.newSetFromMap
.
中的闭包
我认为在 Ignite 中存储您的自定义设置有点混乱。例如,您不能使用 SQL 查询集合。因此,最好的解决方案是以不同方式对数据建模。
如果你真的想走这条路,如果你把你的 class 的副本放在 server-side 上它应该可以。
当我尝试将数据放入缓存时,Apache ignite 抛出以下异常,
Caused by: class org.apache.ignite.IgniteCheckedException: Failed to deserialize object with given class loader: [clsLdr=org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager$CacheClassLoader@5d5b5fa7, err=Failed to deserialize object [typeName=java.util.Collections$SetFromMap]]
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.apache.ignite.internal.marshaller.optimized.OptimizedObjectInputStream.readSerializable(OptimizedObjectInputStream.java:608)
... 43 more
Caused by: java.lang.ClassNotFoundException: com.example.springapachecache.HelloWorld
计划:
package com.example.springapachecache;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder;
import java.util.*;
public class HelloWorld {
public static void main(String[] args) throws IgniteException {
// Preparing IgniteConfiguration using Java APIs
IgniteConfiguration cfg = new IgniteConfiguration();
// The node will be started as a client node.
cfg.setClientMode(true);
// Classes of custom Java logic will be transferred over the wire from this app.
cfg.setPeerClassLoadingEnabled(true);
// Setting up an IP Finder to ensure the client can locate the servers.
TcpDiscoveryMulticastIpFinder ipFinder = new TcpDiscoveryMulticastIpFinder();
ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509"));
cfg.setDiscoverySpi(new TcpDiscoverySpi().setIpFinder(ipFinder));
// Starting the node
Ignite ignite = Ignition.start(cfg);
IgniteCache<Integer, Set<String>> setCache = ignite.getOrCreateCache("mySetCache");
System.out.println("setCache before: "+setCache.get(1));
Set<String> meetingUuids = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>() {
// Set backed by LRU map.
private static final long serialVersionUID = -8251614405342939979L;
@Override
protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) {
return size() > 1000;
}
});
meetingUuids.add("meetingId");
// Set<String> meetingUuidSet = new HashSet<>(meetingUuids);
// setCache.put(3, meetingUuidSet);
setCache.put(1, meetingUuids);
System.out.println("setCache after: "+setCache.get(1));
// Disconnect from the cluster.
ignite.close();
}
}
使用简单的 linkedHashMap(Set meetingUuids = Collections.newSetFromMap(new LinkedHashMap
您在最后一段中暗示了问题。您可以在 Ignite 中存储 Sets,并且可以通过网络“对等 class 加载”代码。您不能 做的是对等class 加载“模型”中使用的代码,即用于定义缓存的任何class。在您的示例代码中,这是 Collections.newSetFromMap
.
我认为在 Ignite 中存储您的自定义设置有点混乱。例如,您不能使用 SQL 查询集合。因此,最好的解决方案是以不同方式对数据建模。
如果你真的想走这条路,如果你把你的 class 的副本放在 server-side 上它应该可以。