33

アプリサーバーで複数のウェブアプリを実行していて、各ウェブアプリのWARファイルに同じjarファイルのコピーが含まれています。

これは、そのjarファイル内のクラスがJVMに複数回ロードされ、それが存在するWARファイルごとに1回ロードされることを意味しますか?続いて、そのようなクラスに静的同期メソッドがある場合、それはWebアプリ内のスレッド間でのみ同期されますが、同じクラスの同じメソッドに対して、別のjarファイルの別のファイルで同期されませんか? WARファイル?(質問が理にかなっていることを願っています。必要に応じて明確にします)。

この場合、最善の解決策は、各WARファイルからjarファイルを削除し、サーバー上の共有クラスパスフォルダーにデプロイすることだと思いますか?

4

3 に答える 3

38

Javaクラスローダーは通常、固定された順序で1つ以上の場所でクラスを探すことによって機能します。たとえば、コマンドラインからアプリケーションを実行するときにアプリケーションをロードするクラスローダーは、最初にrt.jarファイル(およびブートクラスパス上の他のファイル)を検索し、次にクラスパスで指定されたディレクトリとJARファイルを検索します。

Webアプリのクラスローディングは原則的には似ていますが、実際にはもう少し複雑です。特定のWebアプリの場合、Webアプリケーションのクラスローダーは次の順序でクラスを検索します。たとえば、Tomcat6は次の順序でクラスを検索します。

  1. JVMのブートストラップクラス
  2. システムクラスローダークラス(ここで説明)
  3. / WEB-INF/webappのクラス
  4. Webアプリの/WEB-INF/lib/*.jar
  5. $ CATALINA_HOME / lib
  6. $ CATALINA_HOME / lib/*。jar

もちろん、クラスローダーが探しているクラスを見つけると、それ以上は検索されません。そのため、順序の後半にある同じ名前のクラスはロードされません。

複雑なのは、WebコンテナにはWebアプリケーションごとに1つのクラスローダーがあり、これらのクラスローダーは共通のクラスを管理する他のクラスローダーに委任することです。実際には、これは、一部のクラスがコンテナ全体に対して1回だけロードされることを意味し(たとえば、1と2)、他のクラスは異なるクラスローダーによって複数回ロードされる可能性があります。

(クラスが複数回ロードされると、個別のClassオブジェクトと個別のクラススタティックが生成されます。JVMに関する限り、クラスのバージョンは異なるタイプであり、あるバージョンから別のバージョンに型キャストすることはできません。)

最後に、Tomcatは、個々のWebアプリケーションを「ホットロード」できるように構成できます。これには、Webアプリケーションを停止し、そのWebアプリ用の新しいクラスローダーを作成して、再起動する必要があります。

ファローアップ

それで...静的メソッドを同期しても、クラスが複数回ロードされている共有リソースへのアクセスは保護されませんか?

詳細にもよりますが、おそらくそうではありません。(または、別の方法で、クラスが実際に複数回ロードされているかどうかを確認するには、クラスstaticの各「ロード」のメソッドが異なるstaticフィールドのセットにアクセスします。)

シングルトンアプリケーションクラスインスタンスを同じコンテナ内の複数のWebアプリケーションで共有したい場合は、クラスを$CATALINA_HOME/libまたは同等のものに配置するのが最も簡単です。ただし、これが優れたシステム設計であるかどうかも自問する必要があります。Webアプリを組み合わせるか、共有データ構造の代わりにリクエスト転送などを使用することを検討してください。シングルトンパターンはwebappsで厄介になる傾向があり、このフレーバーはさらに厄介です。

于 2010-11-09T10:36:51.997 に答える
5

Java EEアプリケーションサーバーは通常、複数のクラスローダーを使用してアプリケーションを相互に分離し、他のアプリに影響を与えることなく1つのアプリケーションの新しいバージョンをデプロイできるようにします。

クラスローダーの階層を持つEARに複数のWARファイルや1つのEJBファイルなどのパターンがあり、各WARには独自のパターンがあります。

あなたが説明するように、これは重複につながりますが、これは必ずしも悪いことではありません。これは、同じJARの異なるバージョンを同時にデプロイすることもでき、それは実際には有益であり、新しいバージョンへの増分移行を可能にすることを意味します。

一部のアプリケーションサーバー(例としてWebSphere)は、共有ライブラリの概念を明示的にサポートしており、私はそれを使用しています。

JARを任意のクラスパスにポップするだけでは注意してください。アプリサーバー自体が不安定になるリスクがあります。

于 2010-11-09T10:26:24.027 に答える
0

ほとんどのアプリケーションサーバーは、パスに沿って最も具体的に使用するポリシーを優先します。同じことを行う複数のライブラリがある場合は、それらをアプリケーションサーバーlib(fe:TOMCAT_HOME / lib)内に配置することを検討する必要があります。

于 2010-11-09T10:23:17.573 に答える