2012-02-17 21 views
3

我們遇到了一個奇怪的問題。我們獲得Oracle Coherence緩存的KeySet,但不能直接從緩存中獲取值,即使沒有更新活動。如何通過檢索到的關鍵對象使oracle一致性失敗?

以下代碼一致失敗(即輸出「>>>> 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的對象(未顯示)。

的關鍵對象也有equals()和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; 
} 

相信連貫使用該配置中的序列化的關鍵對象,這將使這兩種方法不相干的哈希值,除了我不知道前端緩存(本地JVM,本地存儲關閉)和後端緩存(存儲節點JVM)都是如此。

我們的部分代碼通過重建鍵,以標準順序插入值來部分解決此問題。這通常的作品。我不明白爲什麼這是必要的,因爲我們的hashCode()方法和HashMap的Java的hashCode()AFAIK對散列的迭代順序不敏感。爲什麼它通常,但不總是作品也是一個謎。

回答

2

答案(感謝,迪米特里)就是HashMap的不保證其系列化的排序,所以系列化哈希 - > deserialize->對象的哈希 - > serialize->系列化哈希可能會導致第二個序列化散列是與第一個不同的字節流。

Java對散列中的排序沒有任何保證,序列化依賴於排序。序列化可以不同於一個JVM到另一個JVM,甚至在同一個JVM中。由於HashMap的內部實現是典型的內存中哈希,其中每個存儲哈希都存儲(可能通過鏈接列表)一組哈希對應於該哈希的條目,哈希條目放入哈希的順序決定(以非特定方式)密鑰集迭代將返回它們的順序。通過比較,A TreeMap應該產生一致的排序,並且因此推測是一致的序列化。

連貫性分區緩存存儲密鑰和值序列化的窗體,因此它們計算序列化版本密鑰的哈希函數,並對序列化密鑰進行相等性檢查。儘管串行化流在重建對象時是等價的,但並不能保證散列和相等性檢查操作所需的相同。

爲了使問題複雜化多,在近高速緩存中,該對象被保持在解串行化的形式,因此它的equals()方法hashCode()方法方法代替。最後,Coherence建議使用其專有的POF序列化,這通常會導致序列化大小減小,並直接控制序列化到要序列化的對象。

+0

我不認爲TreeMap是一個很好的例子,因爲在後續的添加/刪除操作之後,不能保證樹的內部結構是一致的,即具有鍵{1,2}的樹可以具有包含1或2的根節點,這取決於樹上以前的操作。 – javaPhobic 2013-10-02 01:43:34

相關問題