
在使用hazelcast的replicatedmap时,尤其当配置了inmemoryformat.binary并启用了统计功能 (setstatisticsenabled(true)) 时,可能会遇到java.lang.classcastexception。该异常通常发生在hazelcast内部尝试收集replicatedmap的运行时指标时,日志中会显示类似以下内容:
java.lang.ClassCastException: class java.lang.String cannot be cast to class com.hazelcast.internal.serialization.impl.HeapData
...
at com.hazelcast.replicatedmap.impl.ReplicatedMapService.provideDynamicMetrics(ReplicatedMapService.java:387)
at com.hazelcast.replicatedmap.impl.ReplicatedMapService.getStats(ReplicatedMapService.java:357)
at com.hazelcast.replicatedmap.impl.ReplicatedMapService.getLocalReplicatedMapStats(ReplicatedMapService.java:197)
at com.hazelcast.replicatedmap.impl.LocalReplicatedMapStatsProvider.getLocalReplicatedMapStats(LocalReplicatedMapStatsProvider.java:85)
...从堆栈信息可以看出,问题发生在LocalReplicatedMapStatsProvider.getLocalReplicatedMapStats方法内部,具体是在尝试获取内部数据记录的堆内存开销时。原始的Hazelcast配置示例如下:
import com.hazelcast.config.Config;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.ReplicatedMapConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.replicatedmap.ReplicatedMap;
public class HazelcastConfigExample {
private static HazelcastInstance setupHazelcastConfig() {
Config config = new Config();
config.setInstanceName("rogueUsers");
NetworkConfig network = config.getNetworkConfig();
network.setPort(5701).setPortCount(20);
network.setPortAutoIncrement(true);
JoinConfig join = network.getJoin();
join.getMulticastConfig().setEnabled(true);
HazelcastInstance hz = Hazelcast.getOrCreateHazelcastInstance(config);
ReplicatedMapConfig replicatedMapConfig =
config.getReplicatedMapConfig("rogueUsers");
// 关键配置:内存格式为BINARY,并启用统计
replicatedMapConfig.setInMemoryFormat(InMemoryFormat.BINARY);
replicatedMapConfig.setAsyncFillup(true);
replicatedMapConfig.setStatisticsEnabled(true); // 导致问题的根源之一
replicatedMapConfig.setSplitBrainProtectionName("splitbrainprotection-name");
// 问题所在:ReplicatedMap泛型声明为String, String
ReplicatedMap<String, String> map = hz.getReplicatedMap("rogueUsers");
// map.addEntryListener(new RogueEntryListener()); // 假设存在监听器
return hz;
}
public static void main(String[] args) {
HazelcastInstance instance = setupHazelcastConfig();
// 可以在这里进行map操作,例如:
// ReplicatedMap<String, String> map = instance.getReplicatedMap("rogueUsers");
// map.put("user1", "statusA");
// System.out.println(map.get("user1"));
}
}当ReplicatedMapConfig的inMemoryFormat设置为InMemoryFormat.BINARY时,Hazelcast会将存储在Map中的对象序列化成二进制形式,即com.hazelcast.internal.serialization.Data接口的实现类(例如HeapData)。这种格式有助于节省内存和优化网络传输。
ClassCastException的发生,是由于在LocalReplicatedMapStats类的第85行左右,Hazelcast内部在计算内存使用量时,期望获取的是HeapData类型的内部记录,但实际获取到的却是String类型,导致了强制类型转换失败。
// 简化后的内部代码逻辑,来自LocalReplicatedMapStats
boolean isBinary = (replicatedMapConfig.getInMemoryFormat() == InMemoryFormat.BINARY);
if (isBinary) {
// 当 isBinary 为 true 时,期望 record.getValueInternal() 返回 HeapData
memoryUsage += ((HeapData) record.getValueInternal()).getHeapCost(); // <-- 异常发生处
}这意味着,尽管我们配置了InMemoryFormat.BINARY,且期望所有数据都以二进制Data的形式存储,但在某些情况下(可能与ReplicatedMap的特定实现或版本有关),当Map的泛型声明为ReplicatedMap<String, String>时,Hazelcast的统计模块在尝试访问内部数据时,未能正确地将其识别为HeapData,反而得到了原始的String对象,从而引发了类型转换错误。
为了解决这个ClassCastException,一种有效的解决方案是显式地将ReplicatedMap的泛型类型声明为com.hazelcast.internal.serialization.Data。Data是Hazelcast内部序列化服务处理二进制形式对象的基本单元。
修改后的配置代码如下:
import com.hazelcast.config.Config;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.JoinConfig;
import com.hazelcast.config.NetworkConfig;
import com.hazelcast.config.ReplicatedMapConfig;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.replicatedmap.ReplicatedMap;
import com.hazelcast.internal.serialization.Data; // 引入Data类
import com.hazelcast.spi.serialization.SerializationService; // 引入SerializationService
public class HazelcastConfigFixedExample {
private static HazelcastInstance setupHazelcastConfig() {
Config config = new Config();
config.setInstanceName("rogueUsers");
NetworkConfig network = config.getNetworkConfig();
network.setPort(5701).setPortCount(20);
network.setPortAutoIncrement(true);
JoinConfig join = network.getJoin();
join.getMulticastConfig().setEnabled(true);
HazelcastInstance hz = Hazelcast.getOrCreateHazelcastInstance(config);
ReplicatedMapConfig replicatedMapConfig =
config.getReplicatedMapConfig("rogueUsers");
replicatedMapConfig.setInMemoryFormat(InMemoryFormat.BINARY);
replicatedMapConfig.set以上就是解决Hazelcast ReplicatedMap中ClassCastException与BINARY内存格式的兼容性问题的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号