1. 問題
2. キーワード コンパイル、マジックナンバー、定数プール、リテラル、データテーブル、スタック、メソッド領域、プログラムカウンタ、メモリ参照、メモリオーバーフロー、ガベージコレクター、新規領域、*** 領域、命令セット 3. 全文の要約 この記事では、クラス ファイルの構造、仮想マシンがクラス ファイルをロードするメカニズム、クラス ファイルのライフ サイクル、バイトコード ロード エンジンをマクロとミクロの観点から紹介し、仮想マシンの動作に対する理解をより立体的に深めます。 4.CLASSファイル構造解析 私たちは、JAVA 言語を初めて学んだ日から、JAVA/JAVAC コマンドを実行してきました。 JAVAC は、拡張子 .java で作成したテキスト ファイルを、拡張子 .class のバイトコード ファイルにコンパイルします。前の章では、コードの本質を紹介し、JAVA 言語の文法要素について学びました。 Java ファイルをテキスト エディターで開くと、Java 言語の文法仕様に準拠した使い慣れた Java コードが含まれています。しかし、私たちは授業の内容にあまり詳しくありません。前の章では、コードがコンパイラによってマシン命令に変換されることを学びました。では、クラス ファイルも Java 仮想マシンによってマシン命令に変換される命令なのでしょうか? 実際、Java ファイルがクラス ファイルにコンパイルされると、Java 言語とは何の関係もなくなります。命令実行エンジンは JVM 仮想マシンです。 Scala、Python などの他のプログラミング言語は、クラス ファイルにコンパイルしてから、JVM に配置して実行できます。このように、クラス ファイルの性質を調査することがさらに必要になります。 4.1 CLASSファイルの例 まず、ミクロの観点からクラスファイルの構造を紹介しましょう。まず、単純な Java テキスト ファイルを作成し、それをクラス ファイルにコンパイルして、クラスの構造を観察します。 まずインターフェース ファイルを定義します。Add.java ファイルは次のようになります。
パッケージ名の定義のため、com/lzh/jvm のファイル ディレクトリを構築し、現在のディレクトリで com/lzh/jvm/Add.java ファイルと com/lzh/jvm/AddImpl.java ファイルをコンパイルする必要があります。 Add.class ファイルと AddImpl.class ファイルを取得しました。 .java バイナリ ファイルを追加します。 Add.class バイナリ ファイル: AddImpl.java バイナリ ファイル: AddImpl.class バイナリ ファイル: 上記の 4 つの画像は、WinHex バイナリ編集ツールで開かれています。左側はファイルのバイナリコード、右側は ASCII 標準コードなので、英国キーボードの文字のみを表すことができます。中国語の場合は文字化けして表示されます。読みやすくするために、ツールはデータを 16 進形式で表示します。 2 つの 16 進コードは 1 バイトの空間 (8 ビット) を表します。 直感的に、Java ファイルが占めるストレージ スペースはクラスが占めるストレージ スペースよりもはるかに少ないことがわかります。これは、前の章で紹介したコード変換プロセスと一致しています。基本的に、コンピューターは Java ファイルの内容を認識しません。 Java は高級言語であり、その構文は人間の言語に近いですが、コンピューターが理解するのは困難です。したがって、Java ファイルの内容を JVM が認識できるファイル形式に変換する必要があります。 高級言語は言語要素を高度に抽象化しており、それを機械命令に変換するには、コード文を段階的に実行するようにコンピューターを誘導するためのより多くの労力が必要です。次のセクションでは、JVM がクラスの内容をどのように理解して実行するかを理解できるように、クラス ファイルの構造について説明します。 4.2 クラスファイル構造の説明 このセクションでは、上図に示す AddImpl.class を例に、クラス構造を紹介します。構造的には、クラス ファイルには基本フィールドとテーブルの 2 種類のデータのみが格納されます。
4.2.1 マジックナンバー ファイルの種類を判別するために使用されます。通常、ファイルの種類を判断するためにファイルのサフィックスを使用しますが、サフィックスが変更されると、セキュリティ上の問題が発生します。クラスは、クラスの種類を示す 4 バイトのスペースで始まります。 CA FE BA BE はクラス タイプのファイルを示します。 4.2.2 バージョン番号 マジックナンバーの後に、JDK バージョン番号を表す 4 バイトが続きます。
4.2.3 定数プール 名前が示すように、定数プールは文字列定数を格納するために使用されます。文字列定数には次のものがあります。
クラスの本質はテーブルのコレクションであることはわかっていますが、定数プールも例外ではありません。唯一の違いは、定数プールに格納されるテーブルには特定のタイプがあることです。次の表に示すように、合計 11 種類あります (図は「Java 仮想マシン JVM の高度な機能とベスト プラクティスの詳細な理解」から引用)。 各テーブルのテーブル構造は次のように記述されます。 これら 11 種類のテーブルの最初のフィールドはフラグ フィールド タグとして統合されており、1 バイトを占め、テーブルに格納されているデータのタイプを示すために使用されます。 定数プールに入る最初の 2 バイト (u2) は、定数プールの長さ、つまりテーブルの数を表します。 この例では、定数プールの数は 0x0017 であり、これは 10 進数では 23 であることがわかります。 0番目のテーブルは予約インデックスなので、文字列は参照されないということなので、実際のテーブルインデックスは1から計算され、つまり1から23までの22個のテーブルがあることになります。 まず、AddImpl.class 定数プールを観察し、最初のテーブルのテーブル構造を分析しましょう。表から、テーブル番号の直後の u1 の位置は 0A であり、これは 10 進数で 10 であることがわかります。テーブルタイプは CONSTANT_Methodref_info です。テーブル構造から、次の 2 つの u2 位置がテーブルのフィールドに属していることがわかります。どちらのフィールドもテーブル インデックス タイプです。 0x0003 は 3 番目のテーブルを参照することを意味し、0x0013 は 19 番目のテーブルを参照することを意味します。 その後、表は終了し、2 番目の表、最初の表が続きます。テーブル タグは 07 で、CONSTANT_Class_info タイプです。 2 番目のスペースは u2 で、フィールド値は 0x0014 であり、20 番目のテーブルを参照します。 次に、3 番目の表を分析します。同じ方法で、定数プールのテーブル構造を分析できます。定数プールの機能は、ソースコードのすべてのテキストデータを定数プールに集中させることです。さまざまなテーブルが相互に参照し、テキスト データを統一的に管理します。テーブル間の参照により、ほとんどのテキスト データは CONSTANT_Class_info テーブルに格納され、このテーブルではテキスト長の長さフィールドが u2 型であることが規定されており、これは 2 バイト (2 の 16 乗、65536/1024 = 64K) を占めるため、Java 変数またはメソッド名のサイズは 64K を超えることはできません。 4.2.4 アクセスフラグ クラスまたはインターフェースを変更するための資格マーク 定数プールの終了後、2 バイトのアクセス フラグがあり、合計 32 個のフラグ ビットがあります。 4.2.5 クラス/スーパークラス/インターフェースインデックスコレクション クラス インデックス、親クラス インデックス、およびインターフェイス インデックス コレクション: 定数プールの CONSTANT_Class_info テーブルを指し、次に CONSTANT_Class_info テーブル内のインデックスは、特定の CONSTANT_Utf8_info テーブルのバイト フィールドのリテラル値を指します。 4.5.6 フィールドテーブルコレクション フィールドテーブルコレクション: フィールドテーブルの構造は次のようになります 配列は[で表され、フィールドテーブルはクラス内のすべての変数を表すために使用されます(メソッド内のローカル変数を除く) 4.5.7 メソッドテーブルコレクション メソッドテーブルコレクション: メソッドテーブルの構造は次のようになります 4.5.8 プロパティテーブルコレクション プロパティ テーブル コレクション メソッド本体の内容はコード属性にコンパイルされます。コード表の構造は次の通りである コード、例外、行番号テーブル、ローカル変数テーブル、ソース ファイル、定数値、内部クラス、非推奨、合成 クラスファイルは製品の型のようなものです。型を作成するプロセスは、クラスを JVM メモリにロードし、JVM がクラス型の外観に従ってオブジェクトを印刷するプロセスです。重要なポイントは金型の設計にあります。実際、金型自体を製造するには金型セットが必要です。これはクラスの厳密な構造仕様です。クラス ファイル構造仕様では、さまざまな側面での要件が規定されています。この要件に従って作られた金型だけが使用可能であり、製品の製造に使用できます。そうしないと、JVM がクラスが仕様を満たしていないと判断してロードを拒否するのと同じように、製品ラインに載せることさえできません。 5. クラスファイルのライフサイクル クラスの読み込みタイミング ほとんどの場合、クラスは受動的に初期化され、必要がないときには初期化されません。 クラスのロードプロセス
() メソッドは、すべての静的ステートメントをソース コードの順序で実行します。静的変数または静的ステートメントのないクラスには () はありません。 クラスローダー ブートクラスローダー、拡張クラスローダー、アプリケーションクラスローダー クラス ローダーは、親委任メカニズムを使用してクラス ファイルを読み取るため、親委任モデルが破壊されます。たとえば、OSGI サービスはカスタム クラス ローダー メカニズムによって実装されます。各OSGIモジュール(バンドル)には独自のローダーがあります 6. 仮想マシン診断ツール 仮想マシンのパフォーマンス監視およびトラブルシューティング ツール。システムの問題を特定する場合、知識と経験が基礎となり、データが基礎となり、ツールがデータを処理する手段となります。 JDK コマンドラインツール
ヒープダンプファイルを生成する
現時点での仮想マシンのスレッドスナップショット、threaddump、またはJavacoreを生成するために使用されます。 JDK 視覚化ツール
7. 仮想マシンのメモリ削除メカニズム このセクションでは、JVM のメモリ構造、メモリ割り当て操作戦略、およびガベージ コレクション メカニズムをマクロの観点から説明します。 7.1 仮想マシンのメモリ配分 Java メモリ領域とメモリオーバーフロー JVM メモリ領域: メソッド領域、仮想マシン スタック、ローカル メソッド スタック、ヒープ、プログラム カウンター。
7.2 メモリ再利用アルゴリズム メモリリサイクルの概要: コンパイル後、仮想マシン スタック、ローカル スタック、プログラム カウンターによって必要なメモリ領域を決定できます。プログラムの実行後、すべてのメモリ空間は自動的に解放されるため、動的リカバリの最適化は必要ありません。 JVM メモリ チューニングは、主にヒープ領域とメソッド領域という 2 つの主要領域のメモリを対象とします。 参照: 強い、柔らかい、弱い、幻影。強い参照はリサイクルされません。ソフト参照はメモリがオーバーフロー境界に達したときにリサイクルされます。弱い参照は各リサイクル サイクルでリサイクルされ、ファントム参照はリサイクルされたオブジェクトとして明確にマークされます。 メモリの割り当てとリサイクル戦略
3mより大きいオブジェクトは、古いエリアに直接配置されます -XX:PretenureSizeThreshold=3145728(3M)
サバイバー スペース内のオブジェクトはマイナー GC の 1 年後に老化し、15 年以上経過したオブジェクトはオールド スペースに入ります。 -XX:最大テンリングしきい値=15
ガベージコレクションアルゴリズム マークスイープ、コピー、マークコンパクト、世代別コレクション(新生児用はコピー、高齢者用はマークコンパクト) 7.3 メモリコレクター
8. 仮想マシン命令セットアーキテクチャ(実行エンジン) 8.1 仮想マシンバイトコード実行エンジン ランタイムスタックフレーム構造 各メソッド呼び出しの開始から実行完了までのプロセスは、仮想マシン スタックにおけるこのスタック フレームのプッシュからポップまでのプロセスに対応します。
メソッド呼び出しはメソッド実行と同じではなく、呼び出されるメソッドのバージョンを決定します。
スタックベースのバイトコード解釈 説明と実行: スタックベースの命令セットとレジスタベースの命令セット: ローカルインタープリタに基づく実行プロセス クラスローディング実行サブシステムの例 tomcat クラスローディング、OSGI ホットスワップ、バイトコード生成技術、動的プロキシ、Retrotranslator 9. 仮想マシン実装メカニズムの進化 プログラムのコンパイルとコードの最適化 早期コンパイル(コンパイル時)
オーバーロードでは、メソッドに異なるシグネチャ (戻り値を除く) が必要ですが、クラス ファイルでは、次のように記述がまったく同じでない限り、メソッドは共存できます。
後期コンパイル(ランタイム)
10. まとめ JVM は幅広いトピックをカバーしているため、スペースの制限により、この記事では詳細を深く分析することはできません。この記事では、原材料としての CLASS ファイルの構造をミクロの観点から分析し、マクロの観点から JVM が各受信 CLASS をどのように処理するかを説明します。 JVM は論理命令セットのセットをカスタマイズします。これは、コンピューターの実行方法に関する前回の記事にも当てはまります。現代のコンピュータの性能は大きく進歩しましたが、本質的には依然として完全なノイマン アーキテクチャです。量子コンピューティングの急速な発展により、将来のコンピューティングモデルにも革命的な進歩が起こると信じています。 |
<<: リン・コンプ:インテルは中国聯通の 5G エッジコンピューティングのアプリケーションシナリオの拡大と商用化の加速を支援
>>: 2019 年の Hyper-V 監視ツールとソフトウェアのトップ 10
ウェブサイトを構築する際には、特定の分野に突っ込んだり、競合調査を省略したり、ターゲットキーワードを...
一般的に、プロの SEO サービス プロバイダーは、Web サイトの予備診断を行う必要があります。W...
SEO 人材が日々増えるにつれ、あらゆるレベルの「人材」が大企業、中堅企業、中小企業に流れ込んできて...
Meituan.com副社長、王慧文氏(写真提供:テンセントテクノロジー)テンセントテクノロジーの雷...
最近、zgovps から高性能な日本の VPS を購入した人が、OS のインストール方法がわからない...
[51CTO.comからのオリジナル記事] モノのインターネットのすべての応用シナリオの中で、産業用...
多くのウェブマスターが、Baiduの6月28日の事件の影響から逃れられなかったと私は信じています。こ...
VPshared が変ですか?実際、彼はヴィルマックのブランドです! VPShared は、virm...
インテルが今年の第3四半期に、コードネーム「Calpella」の次世代 Centrino モバイル ...
昨夜、私はサンフランシスコで DigitalOcean VPS を開設しました。これは、過去 6 か...
01 データキャプチャ1. 背景調査1) robots.txt をチェックして、サイトのクロールにど...
1. 世界は論争の渦中にあり、CP はワインのランキングについて議論しています。ASOの世界は 2 ...
インターネットの急速な発展に伴い、ますます多くの企業や個人がインターネットを通じて採用や求職のプロセ...
前回の記事では、最も人気のある、絶対に失敗しないセルフサービス Web サイト構築プラットフォーム ...
ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービス文 | 李永華出典 | ...