2011-01-20 6 views
2

私はこれで完全に混乱しています。私は単体テストの完全なパッケージを実行しています。ここでJUnitテストの数で使用されます関連する共有コードがあります:私は何をしないのですHashMap containsKey()が文字列をキーとして失敗する原因は何ですか?

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 

private static Map<String, JAXBContext> jaxbContexts = 
          new HashMap<String, JAXBContext>(); 

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException { 
    JAXBContext context = null; 
    if (jaxbContexts.containsKey(clazz.getName())) { 
     context = jaxbContexts.get(clazz.getName()); 
    } else { 
     context = JAXBContext.newInstance(clazz); 
     System.out.println("Created new context for '" + clazz.getName() + "'"); 
     jaxbContexts.put(clazz.getName(), context); 
    } 
    return context; 
} 

JUnitの実行からコンソール出力は、以下の2つの連続したエントリが含まれて? jaxbContexts.containsKey()は、JUnitの実行中に他の46回とは異なり、このインスタンスでStringベースのキーが動作しないのはなぜですか?テストは並行して実行しているわけではありませんが、違いがある場合はAspectsを使用します。

+0

これらの2つの行の間にJVMの停止/開始がないことは確かですか? – Pointy

答えて

3

デバッグそれとこのgetJAXBContext()メソッドを含むクラスが(それはそれへのすべての呼び出しのためのデバッグモードで同じメモリIDを持っていますチェックすることで)一度だけインスタンス化されていることを確認します。異なるインスタンス化の場合、synchronizedキーワードは異なるロックでロックされ、異なるマップを使用します。

+0

ありがとうございます。デバッグでは、少なくとも静的なjaxbContextのインスタンスが2つあることを確認しました。このコードは、複数の具体的な実装を持つ抽象基本クラスにあります。サブクラスごとにこのフィールドの静的インスタンスが1つありますか? –

+0

@Chris、それが質問に答えるなら、それを受け入れてください。 –

+0

このメソッドは静的ではないため、オブジェクトインスタンス内で同期します(Classインスタンスではなく、異なるロックを提供するため、ロックされません)。マップは静的ですが、ロックなしで同時に使用されるため、containsが完了して追加されるまでの間に、別のスレッドがすでに同じキーに対して同じ処理を実行している可能性があります。 sychronized(jaxContents){ここにすべてのコード}を使用すると動作する可能性があります。 –

1

個人的には、私はcontainsKeyを気にしません。

String name = clazz.getName(); 
context = jaxbContexts.get(name); 
if (context == null) { 
    context = JAXBContext.newInstance(clazz); 
    System.out.println("Created new context for '" + name + "'"); 
    jaxbContexts.put(name, context); 
} 
+0

しかし、これはcontainsKeyが機能していることを示唆する結果には影響しません。問題は実際にはjaxbContextの複数の静的インスタンスにあります。 –

+0

はい、私は実際にこの問題に対処していないことを知っています。だから私は@ Geoffreyの答えに投票した。 –

0
レースを除き

...しかし、あなたは、あなたが並行して物事を実行しないと言う...

とにかく、私はcontext = jaxbContexts.get(clazz.getName())と呼ばれ、nullに対してcontextをテストしているだろう。

ああ、および複数のクラスが同じ名前を持つ可能性があるため、キーとしてクラス自体を使用(クラスローダーを考える)

+0

ありがとうございます。私はもともとクラスそのものをキーとして使用していましたが、この問題の一番下にあるクラス名に切り替えました。 –

1

キーとして文字列を含む地図について何も特別なことは確かにありません。 printlnをnew Exception().printStackTrace()で置き換えると、何が起きているのかがわかります。マップを保持しているクラスのインスタンスを2つ作成しているかもしれません。

-1

マップが簡単に使用するためMap<Class, JAXBContext>の代わりMap<String, JAXBContext>することができます。

関連する問題