質問
次の行に沿って、ロギングクラスで定義された静的オブジェクトがあります。
class myLoggingClass {
static java.util.Properties properties;
...
...
}
参考書によると、これはプロパティオブジェクトがクラスのすべてのインスタンスで共有されることを意味します。
この定義では不十分だと思います。プロジェクトの各アプリケーションで複数回呼び出されるクラスを書いています。
さらに、このプロジェクトでは、同じTomcatコンテナで実行されているいくつかのWebサービスを使用しています。各Webサービスには複数のスレッドがあります。
ホストで実行されているJava仮想マシンは、tomcatの外部で実行される1つ以上のWebサービスクライアントアプリケーションも実行できます。
したがって、この定義により、Tomcatはスレッドを使用して複数のWebサービスを実行し、各スレッドには複数のオブジェクトがあり、クラスのインスタンスが含まれている場合があります。
Tomcatの外部で、同じJVM内で実行されている1つまたは2つのWebクライアントが存在する場合もあります。クラスのこれらのインスタンスのすべては同じプロパティオブジェクトを共有しますか? JVM全体になります。
静的オブジェクトがJVM全体ではない 場合、誰もがどのレベルで存在するかを知っていますか? Tomcatコンテナごとに1つ? Webサービスごとに1つ、スタンドアロンWebサービスクライアントアプリケーションごとに1つですか?
理由:プロパティを更新すると、java.util.Propertiesからjava.lang.ConcurrentUpdateExceptionが発生します。
静的なブール変数を使用して「ロック」します私のクラスがそれを更新するときにプロパティオブジェクトが、これは例外の発生を妨げていません。
これにより、クラスで使用される静的オブジェクトは、java.util.Propertiesで使用されるものと同じスコープレベルにない可能性があると思われますが、それは単なる推測です。
ご協力ありがとうございます。
解決
ConcurrentModificationException
の原因として考えられるのは、あるスレッドで Properties
オブジェクトの値/エントリを繰り返し処理しているときに、別のスレッドが同時に変更していることです。これはできません。
ここで言及しているロックメカニズムについて詳しく説明してください:
静的なブール変数を使用して「ロック」します私のクラスがそれを更新するときにプロパティオブジェクトが、これは例外の発生を妨げていません。
?
Javaで組み込みのロックおよび同期メソッドを使用しているように聞こえないため。
次のようなことにより、別のスレッドがPropertiesオブジェクトを更新している間、スレッドがPropertiesオブジェクトを読み取れないようにする必要があります。
static Object lockObject = new Object();
...
synchronized(lockObject) {
// access the Properties object
}
プロパティオブジェクトにアクセスする毎回には、読み取りまたは変更のいずれかを行う必要があることに注意してください。
また、すべてのインスタンスまたは静的ロックオブジェクト間でデータを共有するために静的オブジェクトを推奨することはありません-グローバルデータは悪ですが、何らかの理由でこれが必要なように聞こえます。
他のヒント
静的は「クラスのすべてのインスタンスで共有されません」 -それらはインスタンスと無関係です。それらはタイプ自体に属します。特に、静的変数は、任意のインスタンスが作成されなくても完全に使用できます。
これは、静的のスコープについての手がかりを与えます:静的クラスのスコープは、包含クラスを表す Class
オブジェクトによってスコープされ、そのオブジェクトは、 ClassLoader
によってスコープされます。ロードしました。
ライブラリの配置場所に応じて、Tomcatが複数のホスティングをサポートしている場合、静的変数はJVM全体またはWebアプリケーション全体になります。
Tomcatのドキュメントを参照して、ライブラリのレイアウト方法とクラスローダーとの関係を確認してください。たとえば、 Tomcat 6.0 ClassLoaderハウツーガイド、および 5.5に相当するもの。
>ブール値の「ロック」方法作業?本当に適切なロック( synchronized
)を使用して、プロパティオブジェクトのすべての使用(読み取りと書き込みの両方、それを反復する期間全体のロックを含む)が適切にロックされるようにします。
「ライブ」を変更する代わりに、 Properties
オブジェクトは、それを不変として扱うことを検討しました。そのため、プロパティを更新する場合は、コピーを取得して変更し、そのコピーを「ライブ」にします。バージョン?まだ2つの異なるスレッドが同時に変更を加えないようにする必要があります(または、一部が失われる可能性があります)が、読み取り側がはるかに簡単かつ効率的になる可能性があります。
このような static
変数のスコープは、クラスをロードしたClassLoaderごとに1つに制限されている場合があります。 TomcatがどのようにClassLoaderを配置するのかわからないので、その環境でスコープの範囲がどの程度になるかを言うのは困難です。
クラスを含むjarが異なるアプリケーションの各WEB-INF / libで複製されるクラスローダーの問題でしょうか? その場合、このjarをアプリケーションではなくTomcatライブラリに追加しようとします。