Tomcat での jar のロードに関する異常な問題の分析と解決

Tomcat での jar のロードに関する異常な問題の分析と解決

現象の説明:

プロジェクトでは、Springboot を使用して Web プロジェクトを開始します。起動フェーズ中に、コンソールに例外が表示されました: 「1.10.3-1.4.3\hdf5.jar システムは指定されたファイルを見つけることができません。」 これらの例外はプロジェクトの正常な動作には影響しませんが、厳格な技術者として、これらの例外を見ることは敵を見るのと同じであり、できるだけ早く排除する必要があります。

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5.jar (指定されたファイルが見つかりません。)
 java.util.zip.ZipFile.open(ネイティブメソッド)
 java.util.zip.ZipFile.<init>(ZipFile.java:225) で
 java.util.zip.ZipFile.<init>(ZipFile.java:155) で
 java.util.jar.JarFile.<init>(JarFile.java:166) で
 java.util.jar.JarFile.<init>(JarFile.java:130) で
 org.apache.tomcat.util.compat.JreCompat.jarFileNewInstance(JreCompat.java:188) で
 org.apache.tomcat.util.scan.JarFileUrlJar.<init>(JarFileUrlJar.java:65) で
 org.apache.tomcat.util.scan.JarFactory.newInstance(JarFactory.java:49) で
 org.apache.tomcat.util.scan.StandardJarScanner.process(StandardJarScanner.java:374) で
 org.apache.tomcat.util.scan.StandardJarScanner.processURLs(StandardJarScanner.java:309) で
 org.apache.tomcat.util.scan.StandardJarScanner.doScanClassPath(StandardJarScanner.java:266) で
 org.apache.tomcat.util.scan.StandardJarScanner.scan(StandardJarScanner.java:229) で
 org.apache.jasper.servlet.TldScanner.scanJars(TldScanner.java:262) で
 org.apache.jasper.servlet.TldScanner.scan(TldScanner.java:104) で
 org.apache.jasper.servlet.JasperInitializer.onStartup(JasperInitializer.java:101) で
 org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5204) で
 org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) で
 org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421) で
 org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411) で
 java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) で
 java.util.concurrent.FutureTask.run(FutureTask.java) で
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) で
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) で
 java.lang.Thread.run(Thread.java:748) で

2019-03-29 18:09:08.303 警告 16940 --- [ost-startStop-1] oatomcat.util.scan.StandardJarScanner: クラスローダー階層から [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86.jar] をスキャンできませんでした

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86.jar (指定されたファイルが見つかりません。)
......
2019-03-29 18:09:08.578 警告 16940 --- [ost-startStop-1] oatomcat.util.scan.StandardJarScanner: クラスローダー階層から [file:/D:/.m2/repository/org/bytedeco/javacpp-presets/hdf5-platform/1.10.3-1.4.3/hdf5-linux-x86_64.jar] をスキャンできませんでした

java.io.FileNotFoundException: D:\.m2\repository\org\bytedeco\javacpp-presets\hdf5-platform\1.10.3-1.4.3\hdf5-linux-x86_64.jar (システムは指定されたファイルを見つけることができません。)

プロジェクト環境の説明

  • tomcat: springboot 組み込みバージョン 8.5.29 を使用する
  • Maven による依存関係管理
  • Spring Bootのバージョンは2.0.1です
  • Springフレームワークのバージョンは5.0.5です
  • このプロジェクトは、Deep Learn 4 Java (優れたJava機械学習ライブラリ) を参照しています。
 <依存関係>
 <groupId>org.deeplearning4j</groupId>
 <artifactId>ディープラーニング4j-コア</artifactId>
 <バージョン>1.0.0-beta3</バージョン>
 </依存関係>

問題のある jar 依存関係

追跡分析

エラーは起動フェーズで報告されるため、起動クラスを見つけてブレークポイントを追加し、どの段階でエラーが報告されているかを段階的に追跡し、エラーの原因を分析します。 Springboot コードをトレースしてデバッグし、jar の読み込み場所を見つけました。主なクラスとメソッドは次のとおりです。

追跡クラス org.apache.tomcat.util.scan.StandardJarScanner

メソッド doScanClassPath(...)

このメソッドは、すべてのクラスローダーをトラバースし、各クラスローダーに jar パッケージをロードします。

上記のアイコンの赤い部分はキーコードで、変数 classPathUrlsToProcess には、ロードするすべての jar 情報、主に jar パッケージのパス情報が格納されます。これは、Maven で見た jar パッケージと同じであることがわかります。

  • メソッド processURLs(...)

このメソッドは、現在のクラスローダーのすべての jar、つまり classPathUrlsToProcess に対してスタック操作を実行し、各 jar パッケージを処理します。キーコードは以下の通りです。

  • メソッド process()

このメソッドは、各jarを読み込んで分析し、

プロセスマニフェスト(jar、isWebapp、classPathUrlsToProcess) 

  • メソッド processManifest

このメソッドは、jar 内のマニフェスト ファイルを処理し、マニフェスト ファイル内のクラス パスを分離し、そのコンテンツを新しい依存 jar として classPathUrlsToProcess に挿入します (processURLs メソッドは、スタック結果に jar をロードします)。

原因分析

実際、問題はマニフェスト ファイルのクラスパスにあります。コードを分析すると、Tomcat は Maven によって管理される jar パッケージをロードするだけでなく、jar 内のマニフェスト ファイルも分析することがわかります。クラスパスがある場合は、その中のコンテンツも jar パッケージの依存関係に追加され、これらの jar パッケージがロードされます。

エラーが発生する場所を確認するために、例として hdf5-1.10.3-1.4.3.jar のマニフェスト ファイルを開きます。

ここでの jar パッケージにはパスもバージョン番号もないため、Tomcat は hdf5-1.10.3-1.4.3.jar のパスに従ってそれをロードすることに注意してください。

ただし、これらの jar はプロジェクト内の対応する場所に存在しないため、jar が見つからないという例外が発生します。実際、プロジェクトにはこれらの jar がありますが、パスと名前は異なります。上の図の左側では、これらの jar がすでに Maven で使用可能であることがわかりますが、名前の後にはバージョン番号が追加されており、パスはそれぞれの Maven リポジトリ内にあります。

この時点で問題の原因がわかったので、次にその解決方法を考えてみましょう。

解決

オプション1:

存在しない jar パッケージがロードされないようにするには、マニフェスト内のクラスパスを削除するか、マニフェスト ファイルを削除します。ただし、Maven が更新されるたびに変更が上書きされ、例外が再度発生する可能性があります。

オプション2:

ロードによって要求されたパスに従って、対応する jar パッケージをコピーし、名前を変更してバージョン番号を削除しますが、これにより jar の冗長性が発生し、同じ jar が 2 回ロードされることになります。

オプション3:

Tomcat バージョンを 8.5.0 以前にダウングレードします。バージョン 8.5.0 では、マニフェストは分析およびロードされないため、例外は発生しません。

オプション4

マニフェスト ファイルをスキャンしないようにコード設定を追加します。

 @ビーン
 パブリックTomcatServletWebServerFactory tomcatFactory() {
  新しいTomcatServletWebServerFactory()を返す{
   @オーバーライド
   保護されたvoid postProcessContext(コンテキストコンテキスト) {
    ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
   }
  };
 } 

要約:

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Tomcat クラスローダーの実装方法とサンプルコード
  • Tomcat を起動したときに Eclipse が Web プロジェクトをロードできない問題を解決する
  • Tomcatのホットデプロイメントとホットロード方式の詳細な説明
  • Tomcat が CSS や JS などの静的リソース ファイルをロードできない場合の解決策
  • Java tomcat のクラスローダーとセキュリティメカニズムをご存知ですか?

<<:  mysql 5.7.20 win64 のインストールと設定方法

>>:  Vue の nextTick について話す

推薦する

MySQLデータベースのQPSとTPSの意味と計算方法

DB ベンチマーク テストを実行する場合、qps と tps はデータベースのパフォーマンスを測定す...

jsはCanvasを使用して複数の画像を1つの実装コードにマージします

解決 関数 mergeImgs(リスト) { const imgDom = document.cre...

ポップアップはすべて不正なものではありません。ウェブサイトのポップアップをデザインするためのヒント

ポップアップニュースは国内のインターネットサービスでは一般的であり、リアルタイムプッシュ方式はウェブ...

MySQL サービスを起動できない問題の解決策を含む MySQL 5.7.17 インストール チュートリアル

.net 開発に関しては、Microsoft の SQL Server データベースに精通しており、...

CSS ボーダーは四隅の実装コードを追加します

1.html <div class="ログインボディ"> <...

ウェブページの色特性の分類

色特性の分類あらゆる色は、赤、緑、青の三原色から構成されます。三原色の中で暖色なのは赤だけなので、作...

Nginx Linux のインストールと展開の詳細なチュートリアル

1. Nginx の紹介Nginxは負荷分散やリバースプロキシにも使えるWebサーバーです。現在最も...

Ubuntu 16.4 で完全に分散された Hadoop 環境を構築するための実践的なチュートリアル

序文この記事は主にubantu 16.4 Hadoop完全分散構築に関する関連コンテンツを紹介し、皆...

Vue は動的な円形のパーセンテージ進捗バーを実装します

最近、小さなプログラムを開発しているときに、次の設計図のような円形のパーセンテージ進捗状況バーを実装...

Centos7 環境でソースコードから mysql5.7.16 をインストールする方法の詳細な説明

この記事では、centos7 環境でソース コードから mysql5.7.16 をインストールする方...

Docker Composeオーケストレーションツールの詳細な説明

Docker の作成Docker Compose は、複数の Docker コンテナを定義して実行す...

Linux でスレッドを作成するための pthread_create の具体的な使用法

pthread_create関数機能紹介pthread_createはUNIX環境のスレッド作成関数...

ページ切り替え効果を作成するための純粋な CSS3 のサンプルコード

前に書いたものは複雑すぎるので、シンプルなコアにしましょう <html> <ヘッド...

MySQL監視グループレプリケーションについて簡単に説明します

元のテキスト: https://dev.mysql.com/doc/refman/8.0/en/gr...

inline-blockプロパティとの互換性

<br />1年前、インターネット上にはinline-blockプロパティに関する記事は...