「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

JVMと言えば、長年働いてきた多くのベテランは、長年レンガを動かし、Javaをツールとして使用しているため、少しイライラするかもしれません。私はJVMの知識がありません。インタビューすることはあります。航空機運搬船、作業中のネジ、自転車。、レンガの移動方法を知っていれば十分です。なぜそんなに多くのことを知る必要があるのですか?強いビジネス感覚があれば、あまり深く理解する必要はありません。もの、ビジネス機能を完了するだけです。雄弁な場合は1つだけです。プログラミングの頭脳、古い鉄は彼の心を沈めます。一緒に理解しましょう。通常はネジを締めるレンチの構造です。これは非常に便利です。それはあなたがさらに進んでより多くを稼ぐことを可能にするからです!

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

### JVM

JVMのいくつかの概念

  • JVMとは

JVMはJavaVirtual Machine(Java Virtual Machine)の略です。JVMはコンピューティングデバイスの仕様であり、実際のコンピューターでさまざまなコンピューター機能をシミュレートすることによって実現される架空のコンピューターです。Java仮想マシンには、バイトコード命令セット、レジスタのセット、スタック、ガベージコレクションヒープ、およびストレージメソッドドメインが含まれています。JVMは、特定のオペレーティングシステムプラットフォームに関連する情報を保護するため、JavaプログラムはJava仮想マシンで実行されるオブジェクトコード(バイトコード)を生成するだけでよく、変更なしで複数のプラットフォームで実行できます。JVMがバイトコードを実行すると、実際にはバイトコードが特定のプラットフォームでのマシン命令の実行として解釈されます。

  • JVMと通常の仮想マシン1.JVM
    はJava仮想マシン(Java仮想マシン)であり、プログラム自体の独立した環境であるJavaバイトコードを実行するための環境には、スタック、レジスタ、バイトコード命令が含まれている必要があります。Java、Android、Scala、Groovy、およびその他の言語はすべてJVMで実行でき、それらはすべてJVMの命令セット、つまりクラス仕様に従います。
    2. VMWare、VisualBoxは、仮想ホストを提供できる完全なPCです。オペレーティングシステムは、この仮想マシンにインストールする必要があります。これは、物理ホストのCPUをシミュレートする命令セットです。

  • JVM、JDK、JRE間の関係

    JVMは基本単位、JREはJavaの動作環境、JDKは開発ツールセットです
    。JVMはJREよりも小さく、JDKよりも小さいです。

1. JavaプラットフォームであるJRE(JavaRuntimeEnvironment、Javaランタイム環境)。すべてのJavaプログラムはJREで実行する必要があります。通常のユーザーは、開発したJavaプログラムを実行してJREをインストールするだけで済みます。

2. JDK(Java Development Kit)は、プログラム開発者がJavaプログラムをコンパイルおよびデバッグするために使用する開発キットです。JDKのツールもJavaプログラムであり、実行するにはJREが必要です。JDKの独立性と整合性を維持するために、JDKのインストール中、JREもインストールの一部になります。したがって、JREファイルを格納するためのjreという名前のディレクトリがJDKインストールディレクトリにあります。

3. JVM(JavaVirtualMachine、Java仮想マシン)はJREの一部です。実際のコンピューターでさまざまなコンピューター機能をシミュレートすることで実現した架空のコンピューターです。JVMには、プロセッサ、スタック、レジスタなどの独自の完全なハードウェアアーキテクチャと、対応する命令システムがあります。Java言語の最も重要な機能は、クロスプラットフォーム操作です。JVMの使用は、オペレーティングシステムに依存しないクロスプラットフォームをサポートすることです。

  • JVM製品とは

    HotSpot、Jrockit、J9


  • JVM1.CとC ++がOSアーキテクチャとCPUアーキテクチャに基づいている理由64ビットバージョンは32ビットでは実行できません。パフォーマンスは非常に高いので、基礎となる実装を記述してください。
    2. JAVAは一度作成すればどこでも実行でき、移植性に優れています。

JVM実行プロセス

1. Javaは、純粋なバイナリバイトコードファイルではなく、クラスファイル、バイトコードファイルにコンパイルされ、オペレーティングシステムで直接実行することはできませんが、純粋なバイナリファイルは直接実行できます。
2. JVMには実行エンジンがあります。JVMがコンパイルされると、さまざまなオペレーティングシステムに対応する命令に変換されます。それをオペレーティングシステムに送信します。すべてのオペレーティングシステムは、独自の命令を認識できます。
3. Windowsはdllプログラムであり、Linuxは.oのダイナミックリンクライブラリです。
「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

JVM構造

1.クラスローダー
2.実行エンジン
3.ランタイムデータエリア
4.ローカルインターフェイス

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

  • ClassLoader

    JVMは.classファイルをロードします。実際、クラスの読み込みとは、クラスの.classファイル内のバイナリデータをメモリに読み込み、それをランタイムデータ領域のメソッド領域に配置してから、ヒープ領域にjava.lang.Classオブジェクトを作成することを指します。クラスのデータ構造をメソッド領域にカプセル化します。クラスロードの最終結果は、ヒープ領域にあるClassオブジェクトです。Classオブジェクトは、メソッド領域のクラスのデータ構造をカプセル化し、Javaプログラマーがメソッド領域のデータ構造にアクセスするためのインターフェイスを提供します。
    同時に、JVM仕様では、クラスローダーが使用されると予想されるときにクラスをプリロードできます。プリロードプロセス中に.classファイルに欠落またはエラーがある場合、クラスローダーはクラスをプリロードします。プログラムで初めてクラスをアクティブに使用すると、エラーレポート(LinkageError)が生成されます。このクラスがプログラムによってアクティブに使用されていない場合、クラスローダーはエラーをレポートしません。

  • 親の委任モデル

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

  • クラスの読み込みプロセス

    1. クラスローダーがクラスロードタスクを受信すると、すぐにはロードを開始しませんが、ロードタスクを親クラスローダーに委任して実行します。クラスの各レイヤーは、最上位のスタートアップクラスまで委任されるまで同じメソッドを使用します。ローダ。親クラスローダーが委託されたクラスをロードできない場合、クラスのロードタスクを次のクラスローダーに返してロードを実行します。
    2. 親委任モデルの作業プロセスは次のとおりです。クラスローダーがクラスロード要求を受信した場合、最初にクラスをロードしようとはしませんが、要求を親クラスローダーに委任して完了します。クラスローダーの各レベルは次のとおりです。このように、すべてのロード要求は、親クラスローダーがロード要求を完了できないと報告した場合にのみ、最終的にトップレベルのスタートアップクラスローダーに送信される必要があります(ロードする必要のあるクラスが検索範囲に見つかりません)。 、サブローダーはそれ自体をロードしようとします。
    3. 親委任メカニズムを使用する利点は、クラスのグローバルな一意性を効果的に保証できることです。同じ修飾名を持つ複数のクラスがプログラムに表示される場合、クラスローダーはロードの実行時に常にクラスの1つのみをロードします。
    4. 親委任モデルを使用してクラスローダー間の関係を整理することには、Javaクラスがそのクラスローダーとともに優先順位の階層関係を持っているという明らかな利点があります。たとえば、rt.jarに格納されているクラスjava.lang.Objectは、このクラスをロードするクラスローダーに関係なく、最終的にはモデルの最上位にあるスタートアップクラスローダーにロードを委託されるため、オブジェクトクラスはプログラム内にありますさまざまなローダー環境は同じクラスです。逆に、親委任モデルが使用されておらず、各クラスローダーがそれを単独でロードする場合、ユーザーがjava.lang.Objectというクラスを作成し、それをプログラムのClassPathに配置すると、さらに多くのJava型システムの最も基本的な動作であるオブジェクトクラスは保証できず、アプリケーションは混乱します。rt.jarクラスライブラリにある既存のクラスと同じ名前のJavaクラスを作成すると、正常にコンパイルできることがわかりますが、ロードおよび実行されることはありません。
    5. 親委任モデルは、Javaプログラムの安定した動作を保証するために非常に重要ですが、その実装は非常に単純です。親委任を実装するためのコードは、java.lang.ClassLoaderのloadClass()メソッドに集中しています。ロジックは明確で簡単です。理解するには:最初にロードされているかどうかを確認します。ロードされていない場合は、親クラスローダーのloadClass()メソッドが呼び出されます。親ローダーが空の場合は、スタートアップクラスローダーが親ローダーとして使用されます。デフォルトでは。親クラスローダーがロードに失敗した場合は、ClassNotFoundExceptionをスローした後、findClassメソッドを呼び出してロードします。

  • 簡単にロードすると、クラスローダーはクラスローダーによるステージを担当し、クラスの完全修飾名に従ってJVMなどのバイナリバイト内部フローを読み取り、実行時メモリ領域のメソッドをゾーンに格納してから変換します。は、ターゲットタイプに対応するjava.lang.Classオブジェクトインスタンスです(Java仮想マシンの仕様では、ヒープ領域に格納する必要があることを明示的に要求していませんが、ホットスポットはクラス一致をメソッド領域に格納することを選択します)、このクラスオブジェクトは将来的に、メソッド領域でこのタイプのさまざまなデータへのアクセスエントリとして使用されます。

  • リンク
    リンク段階で行うことは、JVMにロードされたバイナリバイトストリームのクラスデータ情報をJVMの実行時状態にマージし、検証、準備、分析の3つの段階を経ることです。
    (1)
    検証データ情報がJVM仕様に準拠しているか、有効なバイトコードファイルであるかを検証します。検証内容は、データ情報のフォーマット検証、セマンティック分析、動作検証です。
    フォーマット検証:クラスファイル仕様に準拠しているかどうかを検証します。
    セマンティック検証:finalとしてマークされた型にサブクラスが含まれているかどうかを確認します。クラスのfinalメソッドvideoがサブクラスによって上書きされていることを確認します。親クラス間に非互換性がないことを確認します。およびサブクラス一部のメソッド宣言(同じメソッドシグネチャなどですが、メソッドの戻り値が異なります)
    操作の検証:オペランドスタック内のデータを正しく操作する必要があり、定数プール内のさまざまなシンボル参照を検証します(通常は解析フェーズで実行されます)、リッチリファレンスに記載されている完全修飾名から指定された型を見つけるかどうか、クラスメンバー情報のアクセス修飾子がアクセスを許可するかどうかなどを確認します。)
    (2)
    メモリスペースの割り当てを準備します。クラス内のすべての静的変数に対して、それを設定します。初期値(オブジェクトがまだ生成されていないため、インスタンス変数はこの操作の範囲内にありません)
    は最終的に変更された静的変数であり、元の値が直接割り当てられます。 ;クラスフィールドのフィールド属性テーブルのConstantValue属性、準備段階では、その値はConstantValue値です
    (3)解析
    により、定数プール内のシンボル参照が直接参照に変換されます(クラスのポインターまたはオフセットを取得するか、フィールド、メソッドを直接呼び出すためのメモリ内のメソッド)。これは初期化後に実行できます。
    一部の静的バインディングは解析されますが、動的バインディングは操作中にのみ解析されます。静的バインディングには、いくつかの最終メソッド(オーバーライドされない)、静的メソッド(現在のクラスにのみ属する)、コンストラクター(含まれません)が含まれます。書き直される)

  • 初期化
    は、クラス内のstaticキーワードで識別されるすべてのコードを均一に実行します。実行が静的変数の場合、準備フェーズで設定された初期値は、ユーザーが指定した値で上書きされます。実行が静的コードの場合次に、初期化フェーズで、JVMは静的コードブロックで定義されたすべての操作を実行します。
    すべてのクラス変数初期化ステートメントと静的コードブロックは、コンパイル中にフロントエンドコンパイラによってコレクターに配置され、クラス/インターフェイス初期化メソッドである<clinit>メソッドである特別なメソッドに格納されます。このメソッドの機能は、変数を1つに初期化し、ユーザーが指定した値を使用して、準備フェーズで設定された初期値を上書きすることです。このメソッドはクラスのロードプロセス中にのみJVMによって呼び出されるため、invokeなどのバイトコードは<clinit>メソッドを呼び出すことができません。
    親クラスが初期化されていない場合、親クラスが最初に初期化されますが、親クラスの<clinit>メソッドは<clinit>メソッド内に表示されません。JVMは、の<clinit>メソッドがクラスは、親クラスの<clinit>メソッドが実行される前に実行されます。
    JVMは、クラスが同時に初期化されることを保証する必要があります。複数のスレッドがクラスを同時に初期化する必要がある場合、1つのスレッドのみがクラスの初期化操作を実行でき、残りのスレッドは待機する必要があります。アクティブなスレッドがクラスの初期化操作を実行した後でのみ、待機中の他のスレッドに通知します。

JVMランタイムデータ領域

JVMがJavaコードを実行すると、メモリはいくつかの部分、つまり使用するデータ領域に分割されます。これらの領域には独自の目的があり、JVMプロセスの開始またはユーザースレッドの開始と終了によって作成および破棄されます。

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

  • プログラムカウンタレジスタ


    このポインタを変更して実行する次のバイトコード命令を選択するため、現在の実行スレッドであるバイトコード行番号インジケータの効果

機能
1.スレッドの作成時に作成されます
2.各スレッドには
アドレスがあります3.次の命令を指します

  • メソッド領域(非ヒープ)

    スレッド共有

ストレージ
1.クラス情報
2.定数
3.静的変数
4.メソッドバイトコード

  • VMスタック/ネイティブメソッドスタック

    プライベートスレッド

メソッドが実行されると、ローカル変数テーブル、オペランドスタック、動的リンク、メソッド出口などの情報を格納するためのスタックフレームが作成されます。

メソッドの呼び出しから完了までのプロセスは、スタックフレームを仮想マシンスタックにプッシュしてポップアウトするプロセスに対応します。

ローカル変数テーブルに必要なメモリスペースはコンパイル時に割り当てられ、割り当てられるローカル変数スペースの量は完全に決定され、メソッドの実行中にそのサイズは変更されません。

スタック解除後の空き容量

  • ヒープ

    スレッド共有

ストレージオブジェクトまたは配列

ヒープ分割

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

  • JMM

スレッドワーキングメモリ、メインメモリ

JMMモデル

「インターネットアーキテクチャ」ソフトウェアアーキテクチャ-JVM(パート1)

PS:JVMの概念、JVMとJDKの関係、JVMを使用する理由、JVMの理解、JVMの実行プロセス、クラスファイルがJVM実行エンジンによってデータ領域にロードされ、コンパイルされました。オペレーティングシステムによって認識される命令に。異なるオペレーティングシステムの命令。JVMには、オペレーティングシステムごとに1つのクラスしかありません。クロスプラットフォームを実現します。JVMの実行データは、スレッド共有データ領域(メソッド、ヒープ)とスレッド非依存データ領域(スタック、プログラムカウンター)に分けられます。JVMは実際には基本的に文字通りのものです。わかりにくいかもしれませんが、実務経験があればわかりやすいです。本当に低レベルです。

おすすめ

転載: blog.51cto.com/12040702/2605302