Java ユーザーとしては、JVM のアーキテクチャを習得することも必要です。
Java について話すとき、人々が最初に思い浮かべるのは Java プログラミング言語です。しかし、実際には、Java は、Java プログラミング言語、Java クラス ファイル形式、Java 仮想マシン、および Java アプリケーション プログラム インターフェイス (Java API) の 4 つの側面から構成されるテクノロジです。それらの関係は次の図に示されています。 ランタイム環境は Java プラットフォームを表します。開発者は Java コード (.java ファイル) を記述し、それをバイトコード (.class ファイル) にコンパイルします。次にバイトコードがメモリにロードされます。バイトコードが仮想マシンに入ると、インタープリタによって解釈されて実行されるか、ジャストインタイム コード ジェネレータによって選択的にマシン コードに変換されます。 Java プラットフォームは、Java 仮想マシンと Java アプリケーション プログラミング インターフェイスによって構築され、Java 言語はこのプラットフォームに入るためのチャネルです。 Java 言語で記述およびコンパイルされたプログラムは、このプラットフォーム上で実行できます。このプラットフォームの構造を下図に示します。 Java プラットフォームの構造では、Java 仮想マシン (JVM) が中核にあり、基盤となるオペレーティング システムやハードウェアから独立したプログラムを実現するための鍵となっていることがわかります。その下には移行インターフェースがあり、これはアダプタと Java オペレーティング システムの 2 つの部分で構成されます。このうち、プラットフォームに依存する部分はアダプタと呼ばれます。 JVM は移行インターフェースを通じて特定のプラットフォームおよびオペレーティング システムに実装されます。 JVM の上には、Java の基本クラス ライブラリと拡張クラス ライブラリ、およびそれらの API があります。 Java API を使用して作成されたアプリケーション (アプリケーション) とアプレット (Java アプレット) は、Java 仮想マシン (JVM) によってプログラムとオペレーティング システムの分離が実現され、Java のプラットフォーム独立性が実現されるため、基盤となるプラットフォームを考慮せずに任意の Java プラットフォームで実行できます。 JVM のライフ サイクルには、Java プログラムを実行するという明確なタスクがあります。したがって、Java プログラムが起動されると、JVM のインスタンスが生成されます。プログラムが終了するとインスタンスは消えます。次に、JVM のアーキテクチャと動作プロセスという 2 つの側面から、JVM についてさらに詳しく調べます。 1. Java仮想マシンのアーキテクチャ 各 JVM には 2 つのメカニズムがあります。 ① クラスロードサブシステム: 適切な名前のクラスまたはインターフェースをロードする ②実行エンジン:ロードされたクラスまたはインターフェースに含まれる命令を実行する役割を担う 各 JVM には次のものが含まれます。 メソッド領域、Java ヒープ、Java スタック、ネイティブ メソッド スタック、命令カウンタ、その他の暗黙のレジスタ JVM の学習では、次の部分が最も重要だと私は考えています。 Javaコードのコンパイルと実行のプロセス全体 JVM メモリ管理とガベージコレクションのメカニズム 以下では、これらの部分を個別に説明します。 2. Javaコードのコンパイルと実行の全プロセス 前述したように、Java コードをコンパイルして実行するプロセス全体は、おおよそ次のようになります。開発者が Java コード (.java ファイル) を記述し、それがバイトコード (.class ファイル) にコンパイルされ、バイトコードがメモリにロードされます。バイトコードが仮想マシンに入ると、インタープリタによって解釈されて実行されるか、ジャストインタイム コード ジェネレータによって選択的にマシン コードに変換されて実行されます。 (1)Javaコードのコンパイルは、Javaソースコードコンパイラによって完了します。これは、JavaコードをJVMバイトコード(.classファイル)に変換するプロセスです。フローチャートは次のとおりです。 (2)Javaバイトコードの実行はJVM実行エンジンによって完了する。フローチャートは次のとおりです。 Java コードのコンパイルと実行のプロセス全体には、次の 3 つの重要なメカニズムが含まれます。 Javaソースコードコンパイルメカニズム クラスローディングメカニズム クラス実行メカニズム (1)Javaソースコードコンパイル機構 Java ソースコードのコンパイルは、次の 3 つのプロセスで構成されます。 ①解析して記号表に入力 ②アノテーション処理 ③意味解析とクラスファイルの生成 フローチャートは次のとおりです。 最終的に生成されるクラス ファイルは、次の部分で構成されます。 ①構造情報:クラスファイル形式のバージョン番号、各パーツの数とサイズを含む ②メタデータ:Javaソースコード内の宣言や定数の情報に相当します。クラス/継承されたスーパークラス/実装されたインターフェースの宣言情報、ドメインとメソッドの宣言情報、定数プールが含まれます。 ③メソッド情報:Javaソースコード内の文や式に対応する情報。バイトコード、例外ハンドラテーブル、評価スタックとローカル変数領域のサイズ、評価スタックタイプレコード、デバッグシンボル情報が含まれています。 (2)クラスローディング機構 JVM クラスのロードは、ClassLoader とそのサブクラスを通じて行われます。クラス階層と読み込み順序は次の図で表すことができます。 ①Bootstrapクラスローダー $JAVA_HOME の jre/lib/rt.jar 内のすべてのクラスをロードする役割を担います。これは C++ によって実装されており、ClassLoader のサブクラスではありません。 ②拡張クラスローダー $JAVA_HOME 内の jre/lib/*.jar または -Djava.ext.dirs で指定されたディレクトリ内の jar パッケージを含む、Java プラットフォームの拡張機能のいくつかの jar パッケージをロードする役割を担います。 ③アプリクラスローダー クラスパスで指定されたjarパッケージとディレクトリ内のクラスを記録する責任があります ④カスタムクラスローダー これは、アプリケーションが独自のニーズに応じてカスタマイズする ClassLoader です。たとえば、tomcat と jboss は、j2ee 仕様に従って ClassLoader を実装します。ロードプロセス中に、まずクラスがロードされたかどうかを確認します。検査順序は、カスタム ClassLoader から BootStrap ClassLoader の順で下から上になります。クラスローダーがロードされている限り、このクラスはロードされているとみなされ、このクラスがすべてのクラスローダーによって 1 回だけロードされることが保証されます。読み込み順序は上から下です。つまり、上位層は層ごとにこのクラスを読み込もうとします。 (3)クラス執行メカニズム JVM はスタックベースの仮想マシンです。 JVM は新しく作成されたスレッドごとにスタックを割り当てます。つまり、Java プログラムの場合、その操作はスタックの操作によって完了します。スタックはスレッドの状態をフレームに格納します。 JVM は、スタックに対してフレーム内のプッシュ操作とポップ操作の 2 つの操作のみを実行します。 JVM がクラス バイトコードを実行してスレッドを作成すると、プログラム カウンター (PC) とスタックが生成されます。プログラム カウンターには、メソッド内で実行される次の命令のオフセットが格納され、スタックにはスタック フレームが格納されます。各スタック フレームは各メソッドの各呼び出しに対応し、スタック フレームはローカル変数領域とオペランド スタックの 2 つの部分で構成されます。ローカル変数領域は、メソッド内のローカル変数とパラメータを格納するために使用され、オペランド スタックは、メソッドの実行中に生成された中間結果を格納するために使用されます。スタックの構造を次の図に示します。 3. JVM メモリ管理とガベージコレクションのメカニズム JVM のメモリ構造は、メソッド領域 (メソッド)、スタック メモリ (スタック)、ヒープ メモリ (ヒープ)、ローカル メソッド スタック (Java の jni 呼び出し) に分かれており、構造図は次のとおりです。 (1)ヒープメモリ new によって作成されたオブジェクトのすべてのメモリはヒープ内に割り当てられ、そのサイズは -Xmx と -Xms によって制御できます。 オペレーティング システムには、空きメモリ アドレスを記録するリンク リストがあります。システムはプログラムから要求を受け取ると、リンク リストを走査して、要求されたスペースよりも大きいスペースを持つ最初のヒープ ノードを見つけます。次に、空きノードのリンク リストからノードを削除し、ノードのスペースをプログラムに割り当てます。さらに、ほとんどのシステムでは、この割り当てのサイズがこのメモリ空間の最初のアドレスに記録されるため、コード内の delete ステートメントはメモリ空間を正しく解放できます。ただし、見つかったヒープ ノードのサイズは必ずしも要求されたサイズと正確に一致するとは限らないため、システムは余分な部分を自動的にフリー リストに戻します。この時点で new によって割り当てられるメモリは、一般的に速度が遅く、メモリの断片化が発生しやすくなりますが、使用するには最も便利です。さらに、WINDOWS では、VirtualAlloc を使用してメモリを割り当てるのが最善の方法です。ヒープやスタック内ではなく、プロセスのアドレス空間にメモリの一部を直接予約します。この方法は最も使い勝手が悪いですが、高速で柔軟性も最も高い方法です。ヒープ メモリは、上位アドレスまで拡張されたデータ構造であり、不連続なメモリ領域です。システムは空きメモリ アドレスを格納するためにリンク リストを使用するため、空きメモリ アドレスは自然に不連続になり、リンク リストのトラバース方向は低いアドレスから高いアドレスの方向になります。ヒープのサイズは、コンピュータ システムで使用可能な仮想メモリによって制限されます。これは、ヒープによって取得されるスペースがより柔軟で大きいことを示しています。 (2)スタックメモリ Windows では、スタックは下位アドレスまで拡張されたデータ構造であり、連続したメモリ領域です。この文は、スタックの最上位のアドレスとスタックの最大容量がシステムによって事前に決定されていることを意味します。 WINDOWS では、スタックのサイズは固定されています (コンパイル時に決定される定数)。要求されたスペースがスタックの残りのスペースを超える場合、オーバーフロー プロンプトが表示されます。したがって、スタックから使用できるスペースは少なくなります。スタック上の残りのスペースが要求されたスペースよりも大きい限り、システムはプログラムにメモリを提供します。そうでない場合、スタック オーバーフローを示す例外が報告されます。システムによって自動的に割り当てられ、より高速になります。しかし、プログラマーはそれを制御できません。ヒープ メモリとスタック メモリについて説明する必要があります。 基本データ型はスタック空間に直接割り当てられ、メソッドの仮パラメータはスタック空間に直接割り当てられ、メソッド呼び出しが完了した後にスタック空間から回復されます。参照データ型は、スタック空間にアドレス空間を割り当て、ヒープ空間にオブジェクトのクラス変数を割り当てる new を使用して作成する必要があります。メソッドの参照パラメータはスタック空間にアドレス空間を割り当て、ヒープ空間のオブジェクト領域を指します。メソッド呼び出しが完了すると、スタック スペースから再利用されます。ローカル変数が新しく作成されると、スタック領域とヒープ領域にスペースが割り当てられます。ローカル変数のライフサイクルが終了すると、スタック領域はすぐに再利用され、ヒープ領域は GC による再利用を待機します。メソッドを呼び出すときに渡されるリテラル パラメーターは、最初にスタック スペースに割り当てられ、メソッド呼び出しが完了した後にスタック スペースから回復されます。文字列定数と静的は DATA 領域に割り当てられ、これはヒープ領域に割り当てられます。配列は、配列名としてスタック スペースに割り当てられ、配列の実際のサイズとしてヒープ スペースに割り当てられます。 のように: (3)ネイティブメソッドスタック(JavaでのJNI呼び出し) ネイティブ メソッドの実行をサポートし、各ネイティブ メソッド呼び出しのステータスを保存するために使用されます。ネイティブ メソッド インターフェイスの場合、JVM の実装では必ずしもそのサポートは必要なく、サポートされていない場合もあります。 Sun は移植性を考慮して Java Native Interface (JNI) を実装しました。もちろん、Sun の JNI に代わる他のネイティブ インターフェイスを設計することもできます。ただし、これらの設計と実装は比較的複雑な問題であり、ガベージ コレクターがネイティブ メソッドによって呼び出されているオブジェクトを解放しないようにする必要があります。 (4)方法領域(方法) メソッド コード (コンパイルされた Java コード) とシンボル テーブルを保持します。ロードされるクラス情報、静的変数、最終型定数、プロパティ、メソッド情報を格納します。 JVM は、メソッド領域を格納するために Permanent Generation を使用します。最小値と最大値は、-XX:PermSize と -XX:MaxPermSize を通じて指定できます。 ガベージコレクションの仕組み アプリケーションによって作成されたすべてのオブジェクトはヒープ内に集められます。 JVM には、new、newarray、anewarray、multianewarray などの対応する命令もあります。ただし、C++ には delete や free のような領域を解放するための命令はありません。 Java のすべてのリリースは GC によって行われます。メモリのリサイクルに加えて、GC のもう 1 つの重要なタスクはメモリの圧縮です。これは他の言語でも同様の実装があります。 C++ と比較すると、使いやすいだけでなく、セキュリティも向上しています。もちろん、パフォーマンス上の大きな問題など、デメリットもあります。 4. Java仮想マシンの動作プロセスの例 上記では、仮想マシンのさまざまな部分について詳しく説明しています。次の例では、その動作プロセスを分析します。 仮想マシンは、指定されたクラスの main メソッドを呼び出して起動し、文字列配列パラメータを main に渡します。これにより、指定されたクラスがロードされ、クラスで使用される他の型がリンクされて初期化されます。たとえば、次のプログラムの場合: コンパイル後、コマンドラインモードで次のように入力します: java HelloApp run virtual machine Java 仮想マシンは、HelloApp の main メソッドを呼び出して、3 つの文字列「run」、「virtual」、および「machine」を含む配列を main に渡すことによって起動されます。ここで、HelloApp を実行するときに仮想マシンが実行する可能性のある手順の概要を説明します。 HelloApp クラスのメイン メソッドの実行を開始し、クラスがロードされていない (つまり、仮想マシンには現在クラスのバイナリ表現が含まれていない) ことが検出されるため、仮想マシンは ClassLoader を使用してそのようなバイナリ表現を見つけようとします。このプロセスが失敗すると、例外がスローされます。クラスがロードされた後、メイン メソッドが呼び出される前に、HelloApp クラスを他の型とリンクして初期化する必要があります。リンクは、検証、準備、解決の 3 つの段階で構成されます。検証では、ロードされたメイン クラスのシンボルとセマンティクスがチェックされます。準備では、クラスまたはインターフェースの静的フィールドを作成し、これらのフィールドを標準のデフォルト値に初期化します。解決は、メイン クラスの他のクラスまたはインターフェースへのシンボリック参照をチェックする役割を担います。このステップではオプションです。クラスの初期化は、クラスで宣言された静的フィールドの静的初期化関数と初期化コンストラクターの実行です。クラスを初期化する前に、その親クラスを初期化する必要があります。全体のプロセスは次のとおりです。 |
<<: 2020 年のクラウド コンピューティング開発動向の予測
>>: SaaS、IaaS、PaaS...クラウドコンピューティング業界は急速に熱を帯びている
最近、3つのネットワーク(中国電信、中国聯通、中国移動)は中国への帰路に中国聯通 AS4837 の使...
インターネットの発展のための最も基本的な基盤として、最も理想的なデータセンターにはどのような機能があ...
以前、「新しいアプリをプロモーションする方法」という記事を書きましたが、その中でアプリのプロモーショ...
最近、国内のリベートサイトに関する悪いニュースが相次いでいる。河南省、浙江省、福建省などの多くのリベ...
SEO業界の競争はますます激しくなっています。SEOを始めるのは難しくありません。ウェブサイト編集者...
昨日、4月28日土曜日、私は厦門インタラクティブタイムズ文化コミュニケーション株式会社が開催したMa...
最近、ブルージャイアントIBMはコンサルティング会社に委託し、「クラウド時代におけるオープンソースの...
新浪科技報4月10日午後、A8ミュージックは本日、国家新聞出版広電総局(旧国家新聞出版総局)が発行す...
CDN は通常、複数の地域にある複数のデータセンターにインターネット上で展開される大規模な分散システ...
[[430375]]はじめに: 分散ストレージは、高いスケーラビリティと持続可能な進化という特徴を備...
現在、消費者部門の IoT デバイスの数は産業部門のそれを上回っていますが、IIoT への投資は、業...
現在から11月12日まで、ホステオンズの4つのデータセンター(ロサンゼルス、ラスベガス、ニューヨーク...
[[332331]]みなさんこんにちは。私は梁旭です。ご存知のとおり、Linux ではデバイス ファ...
SEO を行う際、私たちは特定のルールを持つ検索エンジンと対峙します。ウェブサイトが検索エンジンに優...
クラウド コンピューティングには数多くの困難な課題があります。現在、多くの企業がクラウドに移行してい...