web-dev-qa-db-ja.com

libディレクトリからjarファイルをロードする順序

Tomcat内のlibディレクトリからjarファイルがロードされる順序を説明できる人はいますか?アルファベット順ですか?無作為に?または他の注文?

36
Damien

それはすべて TomcatのClassLoading HOW-TO で説明されています。必ずしもアルファベット順ではありません。その動作を観察した場合、Webアプリをサーバー間で移植可能にする場合は、絶対に信頼しないでください。たとえば、Tomcat 6は「偶然」注文しますが、Tomcat 8は注文しません。

要約すると、読み込み順序は次のとおりです。

  1. ブートストラップ/システム(JRE/lib、次にserver.loader
  2. webappライブラリ(WEB-INF/classes、次にWEB-INF/lib
  3. 共通ライブラリ(common.loader、次にTomcat/lib
  4. webapp共有ライブラリ(shared.loader

JAR Xがロードされることを保証したい場合after JAR Yの場合、上記のリストにlaterが現れる場所の1つにJAR Xを配置する必要があります。 。

ただし、例外があります Tomcat docs

最後に、Webアプリケーションクラスローダーは、Tomcatによって実装される仕様(サーブレット、JSP、EL、WebSocket)のJavaEE APIクラスの最初に常に委任します。 Tomcatの他のすべてのクラスローダーは、通常の委任パターンに従います。

つまり、webappにJavaEEクラス(javax.*)、Tomcatは無視します。

ローダーごとに、クラスはインポート/実行する必要があり、まだロードされていない場合は常にJVMによって順番にロードされます。

36
BalusC

実際、それはisアルファベット順です! (特定のディレクトリ内、たとえば元の投稿者が言及している「lib」ディレクトリ内)

具体的には、Tomcat 6のソースをクラスFileDirContextで見ると、メソッドlist()は、見つかったjarのファイル名の配列でArrays.sort()を呼び出します。

私もこれを手動でテストしました。 HelloWorld.getGreeting()を呼び出すJSPでwarを作成し、わずかに異なるバージョンのHelloWorldを含む2つのほぼ同一のjarをWEB-INF/libディレクトリに配置します。 1つは「こんにちは、世界」、もう1つは「さようなら、残酷な世界」と言います。

「Hello、world」バージョンにa.jar、「goodbye」バージョンにb.jarという名前を付け、Tomcatを再起動すると、「Hello」テキストが表示されます。 jarに別の方法で名前を付けてTomcatを再起動すると、「Goodbye」テキストが表示されます。

私が判断できた限り、この動作は文書化されておらず、指定されていないため、これに依存すべきではありません。しかし、今のところはアルファベット順になっています。

32
Charles Roth

WEb-INF/libフォルダーにロードされたjarの順序。

Tomcat 5-7の場合、順序はアルファベット順です。ソートを使用します。

Tomcat 8の場合、基礎となるファイルシステムによってランダムに決定されます。

https://issues.Apache.org/bugzilla/show_bug.cgi?id=57129

23
user2193008

BalusCの回答に完全に同意します。追加する唯一のポイントは、それぞれのクラスローダーからJARをロードするときにアルファベット順をチェックすることです。

Webアプリケーションに「XSSFWorkbook」をロードしてExcelシートからデータを読み取る状況があり、2つのJARS「poi-ooxml-3.9.jar」と「org.Eclipse.birt.runtime_4.3.1.v20130918-1142.jar」がありました同じクラス名とパッケージ構造を持つ。私は単に後者を差し戻したので、アルファベット順で以前のものの隣になり、それは私のためにトリックをしました。同じものを共有したかっただけです。

幸運を

WebSphere環境では、異なるマシンが異なる順序でjarをロードします。したがって、私はuser2193008に同意します。本番環境でクラスローダーの問題が発生し、同じコードが下位環境で正常に機能します。 lib内の重複するjarを削除することで問題を修正しました。たとえば、spring jarにはspring_v1.jarとspring_v2.jarの2つのバージョンがあります。

0
Feng Zhang