如何使用检索到的密钥对象来破坏oracle一致性?

时间:2012-02-17 23:59:28

标签: java caching oracle-coherence

我们遇到了一个奇怪的问题。我们获得了Oracle Coherence缓存的KeySet,但是无法直接从缓存中获取值,即使没有更新活动也是如此。

以下代码一致失败(即输出“>>>> NULL”,因为未检索到该对象)。问题是:为什么?

    NamedCache nc = CacheFactory.getCache(cacheName);
    Set<Object> keys = (Set<Object>)nc.keySet();
    for ( Object key : keys ) {
        Object o = nc.get(key);
        if ( o == null ) {
            System.out.println(">>>>NULL:"+keyStr);
        } 
    }

缓存是具有多个索引的分区命名缓存。

键是一个对象(未显示),带有一个实例变量,一个HashMap。

key对象还有eq​​uals()和hashCode()方法,如下所示:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((values == null) ? 0 : values.hashCode());
    return result;
}


@Override
public boolean equals(Object obj) {
    System.out.println("EQUALS");
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    AbstractCacheKey other = (AbstractCacheKey) obj;
    if (values == null) {
        if (other.values != null)
            return false;
    } else if (!values.equals(other.values))
        return false;
    return true;
}

我相信Coherence在这个配置中使用了序列化密钥对象的哈希,这会使这两个方法无关,除了我不知道前端缓存(本地JVM,关闭了localstorage)和返回缓存(存储节点JVM)。

我们的一些代码通过重建密钥,以标准顺序插入值来部分解决此问题。这个通常有效。我不明白为什么这是必要的,因为我们的hashCode()方法和Java的HashMap的hashCode()是AFAIK,对散列的迭代顺序不敏感。为什么它通常,但并不总是有效也是一个谜。

1 个答案:

答案 0 :(得分:2)

答案(谢谢,Dimitri)是 HashMap 不保证其序列化排序,因此序列化哈希 - &gt;反序列化 - &gt; object-hash - &gt; serialize-&gt; serialized-hash 可能导致第二个序列化哈希是与第一个不同的字节流。

Java不保证在散列中进行排序,并且序列化依赖于排序。序列化可以从一个JVM到另一个JVM,甚至在同一个JVM中。由于HashMap的内部实现是典型的内存中哈希,具有N个桶,每个桶(可能通过链表)保存一组其哈希对应于桶的条目,条目被放入哈希的顺序决定(以非指定的方式)键集迭代将返回它们的顺序。相比之下, TreeMap 应该产生一致的排序,因此可能是一致的序列化。

Coherence分区缓存以序列化形式存储密钥和值,因此它们计算密钥序列化版本的哈希函数,并对序列化密钥执行相等性检查。尽管序列化流对于重构对象的目的而言是等效的,但并不保证对散列和等式检查操作的需要相同。

更复杂的是,在近缓存中,对象以反序列化的形式保存,因此使用 equals() hashCode()方法。< / p>

最后,Coherence建议使用其专有的POF序列化,这通常会减少序列化的大小,并直接控制序列化到被序列化的对象。