web-dev-qa-db-ja.com

同じサーバー上の異なるアプリケーションに同じクラスが存在する場合、クラスの読み込みはどのように機能しますか?

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

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

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

33
CodeClimber

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

ウェブアプリのクラスローディングは基本的に似ていますが、実際には少し複雑です。特定のwebappの場合、webappのクラスローダーは次の順序でクラスを検索します。たとえば、Tomcat 6は次の順序でクラスを探します。

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

もちろん、クラスローダーが探しているクラスを見つけたら、それ以上探す必要はありません。したがって、同じ名前のクラスが後から順番に読み込まれることはありません。

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

(クラスが2回以上読み込まれると、個別のClassオブジェクトと個別のクラススタティックが生成されます。JVMに関する限り、クラスのバージョンは異なるタイプであり、1つのバージョンからその他)

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

[〜#〜]フォローアップ[〜#〜]

静的メソッドを同期しても、クラスが複数回読み込まれた共有リソースへのアクセスは保護されませんか?

詳細によって異なりますが、おそらく違います。 (または、別の見方をすると、クラスが実際にが複数回ロードされた場合、クラスの各「ロード」のstaticメソッドは、 staticフィールドの別のセット。)

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

34
Stephen C

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

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

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

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

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

5
djna

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

0