JVMクラスローダーを整理しました

JVMクラスローダーを整理しました

以前面接に行ったとき、面接官から JVM のパフォーマンス チューニングについて質問されました。以前の会社のプロジェクトでは JVM パフォーマンス チューニングに関連する問題に遭遇したことがなかったため (これは会社のアーキテクトが考慮した問題だと感じていたため)、面接官にこの質問をされたときは完全に混乱し、当然ながら最終結果は失敗でした。 。そこで、ギャップを埋めるために、皆さんのお役に立てればと思い、JVM に関する知識を学びました。

[[334689]]

新しい知識を学ぶ前に、まず学習概要を作成し、その学習概要に従って段階的に学習し理解していきます。そのため、JVM の新しいテクノロジーを学習する際には、JVM クラス ローダー、JVM メモリ構造、JVM ガベージ コレクションの 3 つのセクションに分けて学習しました。今日の記事は JVM クラスローダーについてです。

1. JVMとは何か

JVM に関する理論的な知識を学習しているので、もちろん JVM が何であるかを知っておく必要があります。 JVM は Java Virtual Machine の略です。仮想マシンについて話しているところで、仮想マシンとは何なのかと疑問に思う人もいるかもしれません。ここで、仮想マシンの関連する概念を説明します。

  • 仮想マシン: 一連のコンピュータ命令を実行するために使用されるソフトウェアである仮想コンピュータです。仮想マシンは、システム仮想マシンとプログラム仮想マシンに分けられます。
  • システム仮想マシン: VMware など、物理コンピューターを完全にエミュレートし、完全なオペレーティング システムを実行できるソフトウェア プラットフォームを提供します。

プログラム仮想マシン: 単一のコンピュータ プログラムを実行するために特別に設計された Java 仮想マシンなど。 Java 仮想マシンで実行される命令は、Java バイトコード命令と呼ばれます。 (JVM はオペレーティング システム上で実行され、ハードウェアと直接やり取りすることはありません)

したがって、定義によれば、JVM はプログラム仮想マシンであることがわかります。では、JVM はどこにあるのでしょうか?実際、Java を学び始めた当初は、Java の動作環境に応じて、インターネットから JDK インストール パッケージをダウンロードする必要がありました。インストールが完了すると、インストール パスの下に Jdk と jre という 2 つのフォルダーが作成され、Java 仮想マシンは jre フォルダー内にあります。

何かが存在するなら、その存在には理由があるはずです。では、JVM の目的は何でしょうか?それは何に使われますか? JAVA を学んだ人なら誰でも、Java プログラムを実行するには、まず Java ソース プログラム (.java) をプラットフォームに依存しないバイトコード ファイル (.class) にコンパイルし、次にバイトコード ファイルをマシン コードに解釈して実行する必要があることを知っています。説明したプロセスは、Java 仮想マシンによって実行されます (理解のために下の図を参照してください)。 Java 仮想マシンはバイトコード ファイルを解釈するために使用されますが、解釈のプロセスは実際には非常に複雑なプロセスであるため、これが今日お話しするトピックです。


2. クラスの読み込み

まず、クラスロードのプロセス全体を理解しましょう。下の図から、クラスのライフサイクルは、ロード、接続(検証、準備、解析を含む)、初期化、使用(クラスのインスタンス化)、アンロード(ガベージコレクション)の 5 つの段階に分かれていることがわかります。


Java コードでは、クラス (Interface、Enum などのクラス自体を参照) の読み込み、接続、初期化のプロセスがすべてプログラム実行中に完了することは周知の事実です。次に、クラスのロード、接続、初期化について説明します。

クラスのロード: 最も一般的なケースは、既存のクラスの Class ファイル (バイトコード ファイル) をディスクからメモリにロードし、それをランタイム データ領域のメソッド領域に配置し、次にメモリ内に java.lang.Class オブジェクトを作成して、クラスのデータ構造をメソッド領域にカプセル化することです。

クラス接続(3段階に分かれています):

  • 検証: ロードされたクラスの正確性を確認する
  • 準備:クラスの静的変数(クラス変数とも呼ばれる)にメモリを割り当て、デフォルト値に初期化します(たとえば、intのデフォルト値は0です)
  • 分析: クラス内のシンボリック参照を直接参照に変換する

クラスの初期化: クラスの静的変数に値を割り当てます (コード内で上から下に実行されます)

Java プログラムでは、次の 2 つの方法でクラスを使用できます。

  • アクティブ使用
  • 受動的な使用

すべての Java 仮想マシン実装は、各クラスまたはインターフェースが Java プログラムによって「最初にアクティブに使用される」ときに、それらを初期化します。クラスは、最初にアクティブに使用されるときにのみ初期化されることに注意してください。

クラスまたはインターフェースがアクティブに使用され、初期化されている場合(この時点での初期化とは、ロードと接続(接続の3つのステップ、この時点での接続ではクラスの静的変数のメモリの割り当てが完了し、デフォルト値に初期化されるだけであることに注意してください)が完了したことを意味します)

ここでは 7 つのアクティブな用途をまとめました。

  • クラスのインスタンスを作成する
  • クラスまたはインターフェースの静的変数にアクセスするか、静的変数に値を割り当てる
  • クラスの静的メソッドを呼び出す
  • リフレクション(class.forName() など)
  • クラスのサブクラスの初期化
  • Java仮想マシンの起動時にスタートアップクラスとして指定されるクラス
  • JDK1.7 では動的言語のサポートが改善され始めました。

上記の 7 つのケースを除き、Java クラスを使用するその他の方法は、クラスの受動的な使用と見なされ、クラスの初期化にはつながりません。

3. クラスのロード、接続、初期化の詳細な説明

実際、クラスのロードの最終結果は、メモリ内に配置される Class オブジェクトであることがわかっています。 Class オブジェクトは、メソッド領域内のクラスのデータ構造をカプセル化し、メソッド領域内のデータ構造にアクセスするためのインターフェースを Java プログラマーに提供します。

上記の要約に基づいて、クラスがロードされた後にクラス接続が実際に接続ステージに入ることがわかります。接続とは、メモリに読み込まれたクラスのバイナリデータを仮想マシンの実行環境にマージすることです。では、クラス検証には何が含まれているのでしょうか?

  • クラスファイルの構造チェック
  • セマンティックチェック
  • バイトコード検証
  • バイナリ互換性の検証

4. クラスローダー

クラスのロードは実際にはクラスローダーによって行われます。クラスローダーは、JVM の動作を支援する小さな男として想像できます。では、クラスローダーの定義は何でしょうか?以下は私の個人的な理解に基づいた要約です。

クラス ローダー: クラス ローダーは、Java 仮想マシンのメモリ空間にクラスをロードするために使用されます (クラスをロードするためのツール。クラスはクラス ローダーによってロードされる必要があります)。 JDK1.2 バージョン以降では、クラスのロード プロセスで親委任メカニズムが採用されています。このメカニズムにより、Java プラットフォームのセキュリティをより確実に確保できます。この委任メカニズムでは、Java 仮想マシンに付属するルート クラス ローダー (ルート クラス ローダー自体には親ローダーがないため) を除き、残りのクラス ローダーには親ローダーが 1 つだけあります。 Java プログラムがローダー loader1 に Sample クラスのロードを要求すると、loader1 はまず親ローダーに Sample クラスのロードを委任します。親ローダーがロードできる場合、親ローダーはロードタスクを完了します。それ以外の場合は、ローダー loader1 自体が Sample クラスをロードします。

クラスローダーには 2 つの種類があります。

(1)Java仮想マシンの独自のローダー

  • ルート クラス ローダー (BootstrapClassLoader)、スタートアップ クラス ローダーとも呼ばれます。
  • 拡張クラスローダー
  • システム (アプリケーション) クラス ローダー (SystemClassLoader または AppClassLoader)

(2)ユーザー定義クラスローダー

  • java.lang.ClassLoader のサブクラス (すべてのユーザー定義クラス ローダーは抽象クラス ClassLoader を継承する必要があります)
  • ユーザーはクラスのロード方法をカスタマイズできる

クラス ローダーは、クラスをロードする前に、クラスが「初めてアクティブに使用される」まで待つ必要はありません。


5. クラスローダーの親委任メカニズムの詳細な説明

このセクションでは、クラスローダーの親委任メカニズムについて詳しく説明します。父委任機構は親委任機構とも呼ばれます (ソース コードでは parents ではなく parent となっているため、実際には父委任機構と呼ぶべきだと個人的には理解しています)。父委任機構では、各ローダーは親子関係に従っておなじみの構造を形成します (論理的には、次の図のように)。起動クラス ローダーを除き、残りのクラス ローダーには親ローダーが 1 つだけあります。

次のローダーは継承関係にあるように見えますが、実際は包含関係にあります。

父親委任メカニズムの実際の実装を示す例を挙げてみましょう。

​ 上の図の実行プロセスでクラスローダーの親委任メカニズムがどのように実行されるかを詳しく説明します。まず、loader1 と loader2 はカスタムローダーです。 Loader1 は Sample クラスをロードしようとします。父の委任メカニズムによれば、loader1 は Sample クラスを仮想マシンに直接ロードしません。代わりに、読み込みタスクをシステム クラス ローダーに転送して完了させます。次に、システム クラス ローダーはロード タスクを拡張クラス ローダーに転送し、拡張クラス ローダーはそれをルート クラス ローダーに転送して完了させます。ルート クラス ローダーはすでにクラス ローダー階層の最上位レベルであるため、ルート クラス ローダーは Sample クラスを仮想マシンにロードしようとします (ただし、ルート クラス ローダーは Sample クラスを複数の特定のディレクトリからロードされるため、ロードできません)。ルート クラス ローダーはロードを完了できないため、タスクを拡張クラス ローダーに返し (同様に、原理的にはロードできません)、その後、システム クラス ローダーにロードさせます (通常は正常にロードできます)。最後に、このプロセスは loader1 に返され、クラスのロード プロセスが完了したと宣言されます。

6. クラスローダーを取得するいくつかの方法

クラスローダーの種類がわかったので、クラスローダーを取得する方法も理解する必要があります。クラスローダーを取得する 4 つの方法をまとめました。

1 つ目は、現在のクラスの ClassLoader を取得することです。

  1. clazz.getClassLoder()

具体的な実装は以下のとおりです。

  1. クラス<? >   clazz1 =クラス.forName("java.lang.String");
  2. System.out.println(clazz1.getClassLoader());

2番目の方法: 現在のスレッドコンテキストの ClassLoader を取得します。

  1. ​ Thread.currentThread().getContextClassLoader();

具体的な実装は以下のとおりです。

  1. クラスローダーcontextClassLoader =スレッド.currentThread().getContextClassLoader();
  2. System.out.println(コンテキストクラスローダー);

3番目の方法: システム ClassLoader を取得します。

  1. ​ ClassLoader.getSystemClassLoader();

4番目: 呼び出し元のClassLoaderを取得する

  1. ​ DriverManager.getCallerLoader()

また、配列はクラスローダーによって作成されるのではなく、必要なときに JVM によって自動的に作成されることも知っておく必要があります。配列の場合、そのクラス ローダーは要素タイプのクラス ローダーと同じです。要素型がプリミティブ型の場合、配列にはクラス ローダーがありません。

ClassLoader クラス自体はデフォルトで並列処理が可能です。サブクラスが並列読み込みをサポートする場合は、サブクラス自身を登録する必要があります。ユーザー定義のローダーを並列にロードする必要がある場合は、registerAsParallelCapable() を呼び出してローダー自体を構成する必要があります。

7. 結論

上記の要約から、JVM 学習は、アプリケーション フレームワークである spring や springcloud とは異なることが実際にわかります。すぐに行動して、すぐに効果を確認することができます。 JVM はこれとは異なり、多くの理論が関係します。多くの学生は、それは重要ではなく、学ぶことに意味がないと考えるかもしれません。実際、それは武術の練習と同じです。内面の強さが十分に養われて初めて、他の動きを練習することが容易になり、上達し続けることができます。 JVM は内部の強度に相当するため、JVM を学習することは明らかに非常に重要であると考えられます。

上記は JVM クラスローダーの概要です。次の記事では、Java ソース コードと組み合わせてクラス ローダーを理解する方法について紹介します。もちろん、JVM の他のセクションの関連知識のまとめも今後紹介される予定です。

<<:  オープンソースのKVMカーネル仮想化技術とその管理方法の詳細な説明

>>:  申し訳ありませんが、インターネット上で見つかったすべての Redis 分散ロックには脆弱性があります。

推薦する

Hostingcove は 10% オフ、年間 4 ドル、無料ドメイン名、無料の「unspeakable」を提供します

Hostingcove は 2009 年に設立されたホスティング会社です。HostCat はこれを何...

百度最適化ランキングの最近の変動の理由の分析

6月末以来、百度は2つの大きな調整を行い、多くのウェブサイトに影響を与えました。多くのウェブサイトが...

Dockerコンテナ: アプリケーションを正常に終了させる方法

[[411410]]ビジネスの継続的な更新と反復により、コンテナは頻繁に起動および停止されます。コン...

dogyun: 香港 BGP ライン VPS (MG データセンター)、300M 帯域幅、25 元/月、1G メモリ/1 コア/20gSSD/500G トラフィック

Dogyunは数日前に香港MGデータセンターで国際回線付きVPSを開設しました。中国本土に面した国際...

ウェブマスターフォーラムの人気度 横型PK 人気トップ10フォーラム 新着

人気とは通常、グループ内の人物または物の注目度と人気の度合いを指し、人気のあるフォーラムでの人気は、...

Alibaba Cloud がエンタープライズレベルのクラウド災害復旧ソリューションをリリース、ワンクリック災害復旧、コスト 50% 削減

アリババクラウドは5月29日、エンタープライズレベルのクラウド災害復旧ソリューションをリリースした。...

SEOオリジナル記事とソフト記事の違いは何ですか?

私たちはオリジナル記事の代筆業を営んでいますが、クライアントからよく「なぜ私たちのために書いてくれる...

プライベートクラウドプラットフォーム構築における第三者監視の価値に関する議論

プライベートクラウドの構築は非常に複雑です。構築中にサードパーティの監督者を導入すると、需要の確認、...

ゲーム業界の幹部が語る: クラウド サービスを活用してゲーマーの関心を維持する方法

Akamai は、ビデオ ゲームのパイオニア、イノベーター、リーダーにリアルタイムのサービスと保護...

ウェブサイトのドメイン名とサーバーの選択、SEOの詳細に関する考察

初心者は、キーワードの選び方、ドメイン名の選び方、最適なドメイン名の種類など、いくつかの問題で混乱す...

SEO でよく使われる統計表は何ですか?

SEO でよく使用される統計表とは何ですか? 多くの SEO 担当者は、ウェブサイト データの統計表...

企業ウェブサイトが過剰最適化されがちな4つの理由の例

みなさんこんにちは。私の名前は王吉順です。最近、百度が導入した一連のアルゴリズムにより、多くのウェブ...

SEO はチームワークですか?

月収10万元の起業の夢を実現するミニプログラム起業支援プランSEO は一般的にチームワークです。1 ...