SpringBoot プロジェクトの jar パッケージは薄くてスリムです。オンラインで検索したチュートリアルは使用されていません。

SpringBoot プロジェクトの jar パッケージを薄くする


Spring Boot のデフォルトのパッケージ化方法は、依存パッケージ (ファット パッケージとも呼ばれます) を完全にパッケージ化する方法であり、パッケージ化が遅いだけでなく、サイズが大きく、転送も遅くなります。ブート。

背景
現在、マイクロサービス アーキテクチャはますます人気が高まっており、1 つのプロジェクトに 10 個を超える Spring Boot ベースのサービス モジュールが存在するのが一般的です。jar パッケージにパッケージ化されたサービス モジュールが 100M であると仮定すると、完全なリリースには 1G ファイルのアップロードが必要になる場合があります。ネットワーク状況が良好な場合はそれほど気にならないかもしれませんが、コードをリリースするためにイントラネットにコピーしたり、海外のサーバーにアップロードしたりする必要がある場合、作業効率に深刻な影響を及ぼします。

では、入力した Spring Boot の jar パッケージをスリム化する方法はあるのでしょうか?
答えは「はい」です。関連する構成を通じて、Spring Boot がパッケージ化されると、プロジェクトの共通モジュール、偽インターフェースを呼び出す一部の API モジュールなど、頻繁に変更される依存関係パッケージのみがロードされ、それらの固定された依存関係パッケージは直接アップロードされます。指定ディレクトリには、プロジェクトの開始時にコマンドを通じて lib パッケージによってロードされるディレクトリを指定できます。このようにして、入力した jar パッケージは最大でも数 M 未満になり、Spring Boot プロジェクトの jar パッケージのサイズが大幅に削減され、公開と起動の効率が向上します。

補足:
fat jar: Fat jar、出力 jar パッケージにはすべての依存パッケージが含まれます。
利点は他のコマンドを追加せずに直接実行できることですが、欠点は容量が大きすぎて送信が難しいことです。

**thin jar:** はシン パッケージです。出力 jar パッケージには、頻繁に変更される依存パッケージ (通常、プロジェクト内のパブリック モジュールまたは一部の API インターフェイス依存モジュール) のみが含まれます。
メリットはサイズが小さいためプロジェクトのリリース効率が向上することですが、
デメリットは外部依存パッケージにセキュリティ上のリスクがある可能性があること、プロジェクトのMaven依存関係が頻繁に変更されるとメンテナンスが面倒になることです。サーバー上の lib ディレクトリにあるため、問題の場所を特定するのに役立ちません。

スリム化演習
1. Maven パッケージングパラメータを変更する

<build>
ᅠ ᅠ ᅠ ᅠ <plugins>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ <plugin>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ <groupId>org.springframework.boot</groupId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ <artifactId>spring-boot-maven-plugin</artifactId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ <configuration>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ <layout>ZIP</layout>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<includes>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<include>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<groupId>nothing</groupId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<artifactId>nothing</artifactId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ</include>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<include>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<groupId>com.huacloud.tax.rpc</groupId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ<artifactId>common</artifactId>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ</include>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ</includes>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ </configuration>
ᅠ ᅠ ᅠ ᅠ ᅠ ᅠ </plugin>
ᅠ ᅠ ᅠ ᅠ </plugins>
ᅠ ᅠ </build>



例証します:

レイアウトは、
実行可能 jar パッケージの Main-Class のタイプを構成するために使用されます。ここでは、型指定された jar パッケージの Main-Class が PropertiesLauncher になるように、ZIP に設定する必要があります。

include は
、groupId と artifactId (両方が必要であることに注意してください) に従って、jar パッケージを保持する必要があります。nothing は、依存パッケージが存在しないことを表します。これは、インポートされたパブリック サービス モジュール
に依存パッケージが導入されないことを意味します。

2. Maven パッケージングを実行します。
まず mvn clean を実行し、次に mvn package を実行します。

ターゲット ディレクトリにあるパックされたパッケージを D:\web ディレクトリにコピーし、名前をtax-ws-thin-zip.jar に変更します。

解凍ツールを使用して、tax-ws-thin-zip.jar の META-INF ディレクトリにある MANIFEST.MF ファイルを表示します。

Main-Class の値が実際に PropertiesLauncher に変更されていることがわかり、構成が成功したことがわかります。
(なぜMain-ClassをPropertiesLauncherとして設定する必要があるのか​​については、後ほど紹介します)

3. FatJar と ThinJar のボリュームを比較します。

Thin パッケージ Tax-ws-thin.jar の容量は Fat パッケージの容量よりもはるかに小さいことがわかります。

4. lib パッケージを fatJar パッケージから D:\web ディレクトリにコピーします。

5. コマンドでjarパッケージを起動します。

D:\web>java -Dloader.path="D:\web\lib" -jartax-ws-thin.jar
1
起動パラメータloader.pathを使用して、外部依存関係パッケージのロード パスを設定します。

プロジェクトが正常に開始された場合は、構成したアウトソーシング依存関係パッケージの読み込みが有効になったことを示します。

原理の探索
実行可能 jar パッケージの Main-Class を PropertiesLauncher に設定すると、起動パラメーターloader.path を構成することで依存パッケージのロード パスを指定できるのはなぜですか?
まず、Spring Boot 実行可能 jar パッケージの実装原理における Launcher について理解しました。

以下は Spring Boot 公式 Web サイトからの抜粋です。
org.springframework.boot.loader.Launcher クラスは、実行可能 jar のメイン エントリ ポイントとして使用される特別なブートストラップ クラスです。適切な URLClassLoader を設定し、最後に main() メソッドを呼び出すのは、jar ファイル内の実際の Main-Class です。

3 つのランチャー サブクラス (JarLauncher、WarLauncher、PropertiesLauncher) があります。その目的は、(クラスパス上で明示的にファイルではなく) ディレクトリ内のネストされた jar ファイルまたは war ファイルからリソース (.class ファイルなど) をロードすることです。JarLauncher と WarLauncher の場合、ネストされたパスは固定されています。JarLauncher は BOOT-INF/lib/ にあり、WarLauncher は WEB-INF/lib/ および WEB-INF/lib-provided/ にあります。必要に応じて、これらの場所に追加の jar を追加できます。デフォルトでは、PropertiesLauncher はアプリケーション アーカイブの BOOT-INF/lib/ を検索します。追加の場所を追加するには、loader.properties で LOADER_PATH または loader.path という環境変数 (ディレクトリ、アーカイブ、またはアーカイブ内のディレクトリのカンマ区切りのリスト) を設定します。
———————————————

つまり、ランチャー Launcher はプロジェクトの起動に依存するリソースを読み込みます。ランチャーは 3 つ (JarLauncher、WarLauncher、PropertiesLauncher) あります。JarLauncher と WarLauncher がリソースを読み込むためのパスは固定されており、PropertiesLauncher は環境変数loader.path を使用できます。 . リソースをロードする場所を指定します。


レイアウト属性値の説明:

JAR、通常の実行可能 jar
Main-Class: org.springframework.boot.loader.JarLauncher

WAR (通常の実行可能 war) には、
Main-Class: org.springframework.boot.loader.warLauncherにあるサーブレット コンテナの依存関係が必要です。

ZIP、つまり DIR は、JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncherに似ています
(これを覚えておいてください。他のアプリケーション シナリオはほとんどありません)。

PropertiesLauncher 属性の構成

PropertiesLauncher には、外部プロパティ (システム プロパティ、環境変数、マニフェスト エントリ、またはloader.properties) を介して有効にできるいくつかの特別な機能があります。次の表では、これらのプロパティについて説明します。

主な目的
loader.path lib パッケージのロード パス
loader.home は、loader.path 内の相対パスを解決するために使用されます。たとえば、loader.path = lib とすると、${loader.home}/lib がクラスパスの場所 (およびそのディレクトリ内のすべての jar ファイル) になります。このプロパティは、以下の /opt/app の例に示すように、loader.properties ファイルを検索するためにも使用されます。デフォルトは ${user.dir} です。
loader.args main メソッドのデフォルトの引数 (スペースで区切られています)。
loader.main 開始するメイン クラスの名前 (例: com.app.Application)
loader.config.name プロパティ ファイルへのパス (例: classpath:loader.properties)。デフォルトはloader.propertiesです。
loader.system すべてのプロパティをシステム プロパティに追加する必要があることを示すブール フラグ。デフォルトは false です。
詳細については、Spring Boot 実行可能 JAR パッケージに関する公式 Web サイトのドキュメントを参照してください: The Executable Jar Format

トラップ修正
以前、インターネット上で、layout=ZIP を設定しない方法を見たことがありますが、それを直接シンパッケージにパッケージ化した後、起動コマンドで外部依存パッケージの読み込みパスを -Djava.ext.dirs を使用して指定します。 。

D:\web>java -Djava.ext.dirs="D:\web\lib" -jartax-ws-thin.jar
1
原理分析:
-Djava.ext.dirs は Java 自体の ext 設定をオーバーライドします。 ext.dirs で指定されたディレクトリは、ExtClassLoader ローダーによってロードされます。プログラムでこのシステム プロパティが指定されていない場合、ローダーはデフォルトで $JAVA_HOME/jre/lib/ext ディレクトリ内のすべての jar ファイルをロードします。ただし、システム プロパティを手動で指定し、$JAVA_HOME/jre/lib/ext パスを追加するのを忘れた場合、ExtClassLoader は $JAVA_HOME/lib/ext の下にある jar ファイルをロードしません。つまり、一部の機能が失われます。 Java に付属する暗号化および復号化アルゴリズムが実装されています。

したがって、この記述方法で Java デフォルト拡張クラスローダのロードパスを直接強制的に変更すると、何らかの問題が発生しやすくなります。安易に使用しないほうが良いでしょう。

Oracle ドライバー パッケージが見つからない問題
-Djava.ext.dirs を使用して外部依存パッケージの読み込みパスを設定する場合、Oracle ドライバー パッケージを読み込めないという問題が発生します。
-Doracle.jdbc.thinLogonCapability=o3 、Oracle ログインの互換性を構成します

拡張: 親委任メカニズム
ここでは、拡張に関して、Java の親委任ロード メカニズムが関係します。


1. BootStrapClassLoader: ブートストラップ クラス ローダー。クラスローダーはブート時に作成され、JVM カーネルに書き込まれます。これはバイトコード ファイルではなく、C++ で書かれたバイナリ コードであるため、開発者はブートストラップ クラスローダーを取得できません。クラスへの参照はできません。参照によって操作されます。このローダーは、$JAVA_HOME/jre/lib (またはパラメーター -Xbootclasspath で指定) の下にクラス ライブラリをロードします。

2. EXTClassLoader: 拡張クラス ローダー。ExtClassLoader は、$JAVA_HOME/jre/lib/ext (またはパラメーター -Djava.ext.dirs で指定) の下にクラス ライブラリをロードします。

3. AppClassLoader: アプリケーション ローダーは、Java 環境変数 CLASSPATH で指定されたパスの下にクラス ライブラリをロードします。CLASSPATH で指定されたパスは、Systemn.getProperty("java.class.path") を通じて取得でき、上書きできます。 。

4. CustomClassLoader: カスタムローダーはユーザーが定義した CLassLoader で、たとえば tomcat の standardClassLoader がこのカテゴリに属します。

ClassLoader の親委任メカニズム:
1. APPClassLoader がクラスをロードするとき、最初にクラスを単独でロードするのではなく、クラスのロード要求を親クラス ローダー EXTClassloader に委任して完了します。

2. EXTClassLoader がクラスをロードするとき、最初にクラスをロードしようとするのではなく、クラスのロード要求を BootStrapClassLoader に委任して完了します。

3. BottStrapClassLoader がロードに失敗した場合、EXTClassLoader を使用してロードを試みます。

4. EXTClassLoader もロードに失敗した場合は、APPClassLoader を使用してロードしますが、APPClassLoader もロードに失敗した場合は、異常な ClassNotFundException が報告されます。

概要
1. Spring Boot プロジェクトの実行可能 jar パッケージをスリム化する必要があるのはなぜですか?
2. Spring Boot 用の 3 種類のランチャーの説明
3. 外部依存関係をロードするように PropertiesLauncher ランチャーを構成する方法
4. 指摘-Djava.ext を指定することで、 dirs パラメータで外部依存パッケージのロードの問題を実現
5. 拡張機能で Java の親委任ロードメカニズムを説明
6. Oracle ドライバ パッケージで外部依存パッケージをロードできない問題の解決

最後に、
最近のご支援に感謝します。学習は私自身の仕事ではありますが、皆様の「いいね!」、コメント、懸念事項を見るのは本当に励みになります。ありがとうございます。
今後もより質の高い技術記事を発信できるよう努力し、皆様とコミュニケーションをとりながら成長していきたいと思っております。

もっと刺激的なので、私に従ってください。

———————————————
著作権に関する声明: この記事は CSDN ブロガー「Dou Zhe_2013」のオリジナル記事であり、CC 4.0 BY-SA 著作権契約に従い、オリジナルのソース リンクを添付してください。転載とこの声明。
元のリンク: https://blog.csdn.net/w1014074794/article/details/106445145

おすすめ

転載: blog.csdn.net/qq_22905801/article/details/129800023