JVM仮想マシンを徹底的に理解したい場合は、この記事を読んでください。

JVM仮想マシンを徹底的に理解したい場合は、この記事を読んでください。

  [[272380]]

導入

この記事の使い方:

この記事は、検索ツリーのような、仮想マシンのほとんどの知識ポイントのフレームワークです。知識の一部を知りたい場合は、ルート ノードから検索を開始し、知りたい知識が配置されているリーフ ノードまたはサブツリーを見つけます。しかし、すべての知識を 1 つの記事に列挙すると、記事が長くなりすぎて全体の枠組みがわからなくなってしまいます。そのため、この記事では、ナレッジポイントをリンク形式で詳しく紹介します。この記事を通じて、JVM 関連の知識を思い出すことができます。思い出せない箇所があった場合は、該当するリンクをクリックして閲覧することができます。この試験のような学習方法は印象を深めることができ、テキストをじっと見つめて暗記するよりも記憶効果がはるかに高くなります。

コンテンツ

  • Javaのメモリ管理メカニズムについて話す
  • Java仮想マシンプログラムの実行について話す
  • 仮想マシンのパフォーマンス監視とトラブルシューティングについて話す
  • JIT最適化について話す
  • Java メモリ モデル (JMM) について説明します。
  • プロジェクトの推奨

Javaのメモリ管理メカニズムについて話す

C++ と比較すると、Java のメモリ管理メカニズムは大きな特徴です。プログラマーは、メモリを手動で解放するためのコードを書く必要がなくなりました。自分で実行したい場合でも、仮想マシンではこれを行う機会が与えられません (つまり、GC を自動的にトリガーする方法はありません)。仮想マシンは Java のメモリを完全に制御します。これは素晴らしいように思えますが、仮想マシンが不注意になると(結局のところ、仮想マシンはそのようなプログラムを記述できることを知らないので、仮想マシンを責めることはできないと思いますが...)、メモリリークが発生し、問題を見つけるのが難しくなるため、仮想マシンがどのようにメモリを管理しているかを知ることは非常に重要です。

仮想マシンのメモリ管理は、実際には、使用しなくなったオブジェクトを格納するメモリをクリーンアップし、クリアして、新しいオブジェクトを格納するために使用します。したがって、まず次の質問を検討する必要があります。

  • これらの古い物はどこに置かれていますか? (Java ヒープとメソッド領域)
  • 5 つのデータ領域: プログラム カウンター、Java 仮想マシン スタック、ネイティブ メソッド スタック、Java ヒープ、メソッド領域。
  • この廃棄されたオブジェクトの山ではメモリ リークが発生するでしょうか?あるいはもっと流行の言い方をすれば、OOM はあるのでしょうか? (各ゾーンのOOM)
  • これらの場所にオブジェクトはどのように配置されるのでしょうか? (ヒープ内のオブジェクトの作成)
  • 仮想マシンは、オブジェクトを配置した後、どのようにしてそのオブジェクトを再度見つけるのでしょうか? (ヒープ内のオブジェクトへのアクセス)

仮想マシンは、オブジェクトが配置されている場所を認識し、古いオブジェクトがどこにあるかを認識します。次に、Java の優れた機能の 1 つであるガベージ コレクション (GC) について説明します。ガベージ コレクションは、その名前が示すように、これらの古くなったオブジェクトをクリアして、新しいオブジェクトのためのスペースを確保することです。主に以下の点に留意します。

  • どのメモリを再利用する必要がありますか?
  • オブジェクトは、ガベージ コレクションが必要な場所 (Java ヒープとメソッド領域) に配置されます。
  • いつリサイクルされますか? (物体の生死を判定する)
  • オブジェクトが廃棄されるかどうかを判断するアルゴリズム(要点):参照カウント方式と到達可能性分析方式。
  • リサイクル方法は?
  • GC アルゴリズムの原理 (ガベージ コレクション アルゴリズム)
  • 基礎: マークアンドスイープアルゴリズム
  • 効率問題の解決: 複製アルゴリズム
  • 宇宙ゴミ問題の解決: マーク・アンド・スナッチアルゴリズム
  • 進化: 世代別コレクションアルゴリズム
  • GC アルゴリズムの実際の実装:
  • 7 カラバッシュ兄弟、ああ、ゴミ収集人
  • 新世代: シリアル、パーニュー、パラレル スカベンジ
  • 旧世代: シリアル オールド、パラレル オールド、CMS
  • オールラウンダー:G1
  • HotSpot 仮想マシンはどのようにして GC アルゴリズムを効率的に実装するのでしょうか?

オブジェクトがどのようにリサイクルされるかを説明したので、Java のメモリ管理メカニズムに必要な細かい部分は完成しました。つまり、Java のメモリ管理プロセスは次のようになります。

新しいオブジェクトが何であるかに基づいて、それを置く場所を見つけます

新しいオブジェクト用のスペースがメモリ内にない場合は、スペースをクリアするために GC が実行されます。

本当に場所が見つからない場合は、OOM を投げてください...

仮想マシンは通常、世代別コレクション アルゴリズムである GC アルゴリズムの進化バージョンを使用します。つまり、仮想マシンの Java ヒープ内のメモリは、新しい世代と古い世代に分割されます。では、新しいオブジェクトを配置する場所を探す場合、どこに配置すればよいのでしょうか?具体的にはどのように配置すればよいのでしょうか?オブジェクトは配置後に別の場所に移動されますか? GC はいつ実行されますか?何をクリーンアップする必要がありますか? ... Java のメモリ管理メカニズムの詳細については、私の以前の記事をお読みください。

ここまでで、Java のメモリ管理メカニズムについての説明はほぼ終わりました。これで、仮想マシンの制御下でオブジェクトがメモリ内をどのように移動するかがわかりました。しかし、まず第一に、オブジェクトは作成したクラスに従って作成する必要があるので、作成したクラスはどのようにしてメモリ内のオブジェクトになるのでしょうか?さらに、メソッドを実行するためにオブジェクトを作成しますが、このメソッドはどのように実行されるのでしょうか?これらの質問に答えるには、Java 仮想マシンがプログラムを実行する方法を調べる必要があります。

Java仮想マシンプログラムの実行について話す

Java プログラムを実行する場合は、まず Java コードをバイトコード ファイル、つまりクラス ファイルにコンパイルする必要があります。ここではコンパイル プロセスについては説明しません。主にこの Class ファイルの実行方法について説明します。そのため、まず Class ファイルの構成構造を理解する必要があります。

構成構造を理解した後、次に検討する必要があるのは、この .class ファイルをメモリにロードし、メソッド領域 (Java 8 以降は Metaspace になります) 内の Class オブジェクトに変換する方法です。 (クラスの読み込み)。

仮想マシンのクラスロードメカニズムについては、語るべきことがたくさんあります。誰もがそれについて尋ねるのが好きです。実際には、主に次の 3 つのプロセスが含まれます。

  • クラスをロードするタイミング: プログラムが初めてクラスをアクティブに参照するとき。
  • 能動的な引用と受動的な引用とは何ですか?
  • 明示的な読み込みと暗黙的な読み込みとは何ですか?
  • クラスのライフサイクル: ロード - 検証 - 準備 - 解析 - 初期化 - 使用 - アンロード
  • クラスローダー
  • 2 つのクラスが「等しい」かどうかを判断するにはどうすればよいでしょうか?
  • クラスローダーの分類?
  • 親委任モデルとは何ですか?
  • 親委任モデルを破壊しますか?
  • Javaクラスのホット置換の実装
  • クラスローダーをカスタマイズするにはどうすればいいですか?
  • 親の委任モデルを維持する必要があります: ClassLoader を拡張し、findClass() を書き換えます
  • 親の委任モデルを破棄する: loadClass() を直接書き換える

クラスをメモリにロードした後、次のステップでは、このクラス内のメソッドを実行する方法を検討します。 5 つの主要なメモリ領域にある Java 仮想マシン スタックは、サービスと Java メソッドのメモリ モデルであることがわかっているので、まず仮想マシン スタックのスタック フレームの構造を理解する必要があります。仮想マシン スタックのスタック フレーム構造には、次の部分が含まれます。

  • ローカル変数テーブル(重要)
  • オペランドスタックと動的リンクとメソッドの戻りアドレス

メソッドの実行を支援する Java 仮想マシン スタックの構造を理解した後、次のステップは Java クラスでメソッドを呼び出すことを検討することです。象を冷蔵庫に入れるのと同じように、メソッド呼び出しはすぐに実行されるのではなく、次の 2 つのステップに分割されます。

  • メソッド呼び出し: どのメソッドが呼び出されるかを決定する
  • スタックベースの解釈: 実際の実行メソッドのバイトコード

メソッド呼び出しステップを追加する必要があるのはなぜですか?すべてのメソッド呼び出しは、定数プール内のシンボリック参照としてクラス ファイルに保存されるため、必要なメソッドをすぐに実行することはできません。まず、このシンボリック参照 (実際には単なる文字列) に基づいて実行するメソッドを見つける必要があり、このプロセスはメソッド呼び出しと呼ばれます。このメソッドを見つけたら、スタックベースの解釈実行であるこのメソッドの実行を開始します。

メソッドを呼び出すには、まず仮想マシン内のどの命令がメソッド呼び出しを行うことができるか、つまりメソッド呼び出しバイトコード命令を調べてみましょう。

これらのバイトコードは、さまざまなメソッド呼び出しをトリガーします。一般的に言えば、次のようになります。

  • 呼び出しの解析
  • ディスパッチ呼び出し(構文解析呼び出しではシンボリック参照を直接参照に変換する方法がないため、ディスパッチ呼び出しにのみ依存できます)
  • 静的ディスパッチ(メソッドのオーバーロード)
  • 動的ディスパッチ(メソッドオーバーライド)

呼び出すメソッドを決定したら、スタックベースの解釈と実行を開始できます。この時点で、メソッドが実際に実行されます。

さらに、Java の動的型付け言語サポートを理解する必要があります。

仮想マシンのパフォーマンス監視とトラブルシューティングについて話す

よく使用される JDK コマンドライン ツール: JDK コマンドライン ツール。

共通の JVM パラメータ設定が設定されました。一般的な JVM パラメータ設定を参照してください。

仮想マシンのチューニングに関するケース スタディについては、「仮想マシンのチューニングに関するケース スタディ」を参照してください。

JIT最適化について話す

JIT (Just In Time)、つまりジャストインタイムコンパイルですが、まず JIT とは何かを知る必要があります。

次に、HotSpot 仮想マシンにおけるジャストインタイムコンパイラの動作プロセスについては、次の 5 つの質問を通じて調べることができます。

  • インタプリタとコンパイラが共存するアーキテクチャを使用するのはなぜですか?
  • 仮想マシンが 2 つの異なる JIT コンパイラを実装するのはなぜですか?
  • 仮想マシンの階層化コンパイルとは何ですか?
  • ホットコードを識別してコンパイルをトリガーするにはどうすればよいでしょうか?
  • ホットスポットコードとは何ですか? (2種類)
  • 「複数」実行とは何ですか?
  • HotSpotはカウンターベースのホットスポット検出方法を使用しており、2つのホットスポットコードを検出するために、各方法には2つのカウンターがあります。
  • メソッド呼び出しカウンタ
  • バックエッジカウンター
  • HotSpotホットコード検出プロセス
  • ホットコードコンパイルのプロセスとは何ですか?

さらに、JIT は単にホット コードをマシン コードにコンパイルして終了するわけではありません。また、コードの実行も最適化されます。主に次のような古典的な最適化手法があります。

  • 共通部分式の削除 [言語非依存]
  • 配列範囲チェックの削除 [言語関連]
  • メソッドのインライン化 [最も重要]
  • 脱出解析【最前線】

Java メモリ モデル (JMM) について説明します。

この部分は主に並行プログラミングに関連しているため、詳細な紹介は別のリポジトリである Java-Concurrency-in-Practice に移動します。

Java のメモリ モデルは、主に変数の値がメイン メモリ、スレッドの作業メモリ、および Java スレッド (実行エンジン) 間でどのように転送されるかを研究します。つまり、Java メモリ モデルではすべての変数がメイン メモリに格納されることが規定されていますが、各スレッドには独自の作業メモリがあり、その中にメイン メモリからコピーされた変数のコピーが格納されます。 Java スレッドが変数を変更する場合、まず自身の作業メモリ内で変更を行い、その後変更内容をメインメモリに同期します。

これは、コンピューターのストレージ デバイスとプロセッサの計算速度が数桁異なるため、メイン メモリと Java スレッドの間にバッファーとして作業メモリを追加する必要があるためです。ただし、これにより、メイン メモリと作業メモリ間のキャッシュ一貫性の問題も発生します。したがって、2 つの作業メモリ内の同じ変数の値が競合する場合、メイン メモリが変数を同期する順序、つまりどの作業メモリを参照するかを決定するために、特定のアクセス ルールが必要になります。 Java メモリ モデルの主な目的は、仮想マシンが変数をメモリに格納したり、メモリから取り出したりする方法に関するルールを定義することです。

簡単に言えば、Java メモリ モデルの 8 つのアトミック操作を習得し、これらの 8 つの操作を通じて Java メモリ間で変数がどのように転送されるかを知ることです。

実際、Java のメモリ モデルは、並行プロセスにおける原子性、可視性、順序という 3 つの特性をどのように処理するかを中心に構築されています。秩序性を保証するために volatile と synchronized に依存することに加えて、Java 自体にも Happens-Before 原則があります。この原則に基づいて、同時実行環境における 2 つの操作間に競合が発生する可能性があるかどうかを判断できます。

<<:  クラウド コンピューティングの時代において、ハードウェアが依然として重要な理由は何でしょうか?

>>:  AWSテクノロジーサミットが北京で開催され、クラウドコンピューティングの新たなトレンドが明らかに

推薦する

友好的なリンクを交換するときに役に立たない3つの指標:スナップショットPRと重み

最近、友好的なリンクを交換するときに相手が必ず尋ねると言っているウェブマスターをよく見かけます。スナ...

物理的な共同購入はなぜ消滅するのか?百のグループ戦争の啓示

これは、グループ購入が初めて登場した 2010 年に書かれた古い記事です。その年は百連隊作戦の年で、...

ヘルスケア向けクラウドコンピューティングの基本ガイド

ヘルスケア業界がクラウド コンピューティングを使用してデジタル変革を加速し、大量のデータを処理し、コ...

1984hosting: アイスランドのVPSおよび関連ホスティング製品を提供

2006 年に設立されたアイスランドのホスティング会社である 1984hosting は、主にドメイ...

中国建設銀行の林雷鳴氏との独占インタビュー:プラットフォームベースのデジタルオペレーションで社会生態学を強化

[[409364]]インタビューゲスト |中国建設銀行金融技術部ゼネラルマネージャー兼同グループの金...

低品質コンテンツに関する百度の8月22日の発表

最近、Baidu が数回メジャーアップデートを行った後、約 2 か月間観察した結果、一緒に議論できる...

ウェブサイトのページを閲覧する時間の長さは、ウェブサイトに滞在する時間の長さと同じですか? 1つの記事で違いとベストプラクティスを理解する

ページが閲覧される時間の長さは、ユーザーがそのページに滞在する時間の長さと同じではありません。したが...

クラウドコンピューティング環境はネットワークの可視性に課題をもたらす

企業は、クラウド コンピューティング環境の管理を改善し、データセンターの東西トラフィックをより適切に...

怠惰な考え方は、一部のウェブマスターがSEOスキルを向上させるのを妨げます

ウェブマスターが毎日どれだけ大変な仕事をしているかは、誰もがよく知っています。ウェブサイトのコンテン...

銀行におけるクラウドコンピューティングと人工知能の利点

クラウド コンピューティング プロバイダーは、データを分析し、スキルの低いユーザー (または予算が限...

SEO を行うには、詳細から始めて、一度に 1 ステップずつ分析して実行する方法を知る必要があります。

SEO技術は中国で10年近く普及しており、当時のSEOの運用方法は非常にシンプルで、意図的に行えばキ...

虎の骨を描くのは難しいが、皮膚を描くのは難しい。ハオ兄弟の狂気

最近、「Crazy Webmasters」を再び読みました。私が最も興味を持ったのは、本のウェブサイ...

ヒューマニスティックマーケティング:インターネットマーケティングで無視できないサポートポイント

今日最も人気のある業界といえば、それはオンライン マーケティングでしょう。毎日上げ潮のように押し寄せ...

Dynamics 365の中国上陸で発表された情報の徹底分析

[51CTO.comよりオリジナル記事] 中国市場で唯一の国際パブリッククラウドを展開する21Via...

ブローカーの実装ロジック - Kafka ナレッジ システム (パート 3)

[[409670]]前回の記事では、Kafka プロダクション側のロジックと、メッセージがキャッシュ...