3

奇妙な問題が発生しています。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);
        } 
    }

キャッシュは、複数のインデックスを持つパーティション化された名前付きキャッシュです。

キーは、1つのインスタンス変数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;
}

Coherenceは、この構成でシリアル化されたキーオブジェクトのハッシュを使用していると思います。これにより、フロントキャッシュ(ローカルJVM、ローカルストレージがオフになっている)とバックキャッシュ(ストレージ)の両方に当てはまるかどうかわからない場合を除いて、これら2つの方法は無関係になります。ノードJVMの)。

一部のコードは、キーを再構築し、値を標準の順序で挿入することで、この問題を部分的に解決します。これは通常は機能します。hashCode()メソッドとHashMap用のJavaのhashCode()は、AFAIKであり、ハッシュの反復順序に影響されないため、これが必要な理由はわかりません。なぜそれが通常は機能するが、常に機能するとは限らないのかも謎です。

4

1 に答える 1

2

答え (ありがとう、Dimitri) は、HashMapはシリアル化の順序を保証しないため、serialized-hash ->deserialize-> object-hash ->serialize-> serialized-hashを実行すると、2 番目のシリアル化されたハッシュが異なるバイトになる可能性があるということです。最初よりもストリーム。

Java はハッシュ内の順序付けを保証しておらず、シリアライゼーションは順序付けに依存しています。シリアル化は、JVM ごとに異なる場合があり、同じ JVM 内でも異なる場合があります。HashMap の内部実装は典型的なメモリ内ハッシュであり、N 個のバケットがあり、それぞれがバケットに対応するハッシュを持つエントリのセットを (おそらくリンクされたリストを介して) 保持するため、エントリがハッシュに入れられる順序によって決定されます。 (特定されていない方法で)キーセットの反復がそれらを返す順序。比較すると、 TreeMapは一貫した順序を生成する必要があり、したがって、おそらく一貫したシリアル化が生成されます。

Coherenceのパーティション化されたキャッシュは、キーと値をシリアライズされた形式で格納するため、キーのシリアライズされたバージョンでハッシュ関数を計算し、シリアライズされたキーで等価性チェックを実行します。シリアル化されたストリームは、オブジェクトを再構築する目的では同等ですが、ハッシュおよび同等性チェック操作に必要な同一性は保証されません。

さらに複雑なことに、ニアキャッシュでは、オブジェクトは逆シリアル化された形式で保持されるため、代わりにそのequals()およびhashCode()メソッドが使用されます。

最後に、Coherence は独自の POF シリアライゼーションの使用を推奨しています。これにより、通常、シリアライズされたサイズが縮小され、シリアライズされるオブジェクトのシリアライゼーションを直接制御できます。

于 2012-02-26T03:38:26.913 に答える