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 分散ロックには脆弱性があります。

推薦する

vpscreed-クリスマススペシャル: 50% オフ/マネージド VPS/ダブルメモリ

年に設立された vpscreed は、ドイツと米国にデータ センターを持つインドの商人です。マネージ...

エッジコンピューティングが商用 IoT ソリューションの構築にもたらす意味

ガートナーによると、2023年末までに、大企業の50%以上がIoT向けにインストールされた少なくとも...

盲目的にオリジナルコンテンツを作成すると、Web サイトの方向性が失われます。

Baidu がユーザー エクスペリエンスを重視して以来、多くの Web サイトから盗作やコレクション...

中国SEOの現状 簡単にランキングを獲得する方法

Sunshine Home Blog は、いわゆる SEO を行うことは実は非常に簡単なことだと考え...

皆さん、人気の Pinterest のようなサイトはお元気ですか?

偶然Weiboでこの写真を見て、写真の場所がとても気に入ったので、自分でも行ってみたいと思いました。...

十分な利益を上げなくても企業は株式を公開できますか? 58とQunarの資金調達の道筋について

Qunarや58.comを含む一部の企業にとって、株式公開は明らかに投資を求め、発展を続けるための重...

インフラ自動化に必要な3つの段階

従来のオンプレミス データ センターはまだ存在していますが、かつてそこで主流だったワークフローは急速...

携帯電話のマーケティングには多くの混乱がありますが、Qiyitongはユーザーを第一にするという当初の意図を主張しています

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っていますモバイルイ...

vpsunlimited-512M メモリ (XEN)/25G ハードディスク/500G トラフィック/初月 2.99 USD

vpsunlimited は 2010 年に設立され、主に XEN ベースの VPS サービスを提供...

時代遅れのSEOは避けましょう。SEOはそれほど単純ではありません

今日は日中何もすることがなかったので、Moonlight Blog の記事をいくつか読んで、自分がと...

奇電の混乱の背後にあるのは、資本、起業家、ライバルの三つ巴の駆け引き

奇典中国網は山大文学の重要な資産である。最近の人事騒動により、上場への道はより不透明になっている。奇...

SEO診断:サーバーのダウンタイムによりウェブサイトがKになる

みなさんこんにちは。私は徐子宇です。 SEO診断は、私がずっとこだわり続けてきた仕事です。なぜなら、...

クラウド プラットフォームの価格比較: AWS と Azure と Google Cloud

Azure、AWS、Google Cloud は現在、独自のサービス構造、テクノロジー、価格モデルを...

ToBアプリケーションプライベート化配信技術の開発履歴と比較

データのプライバシーとネットワーク セキュリティの考慮事項により、toB シナリオのほとんどの顧客は...

ウェブサイトデータ分析における正しい視点を確立する方法

2012年、Baiduは独自のウェブマスターツールプラットフォームを立ち上げました。ほとんどのウェブ...