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

推薦する

ヤオ・ジンボ:58.comはまだ初期段階にあり、来年には監督者と管理者の10%を削減する予定です。

原題:ヤオ・ジンボ:58.comはまだ初期段階にあり、気を緩める余裕はありません。来年中に監督者と管...

SEO プロモーション: ユーザー生成コンテンツに注目する必要がある理由!

月給5,000~50,000のこれらのプロジェクトはあなたの将来ですコンテンツは王様、外部リンクは女...

SEO担当者の皆さん、上司が何を重視しているか知っていますか?

今日、インターネットで質疑応答を見ました。内容は、SEOについて何も知らない上司に、SEOをうまく行...

#値下げ+アップグレード: Vultr - 20% オフ/10G ポート/14 データセンターへのアップグレード

朗報です。Vultr は、スタッフが過去数年にわたって製品の大規模なアップグレードに取り組んできたこ...

運用上の注意: ユーザーの成長分裂について話すとき、私たちは本当に何を考える必要があるのでしょうか?

ショートビデオ、セルフメディア、インフルエンサーのためのワンストップサービスまず、基本的な理論を明確...

PolarDB-X 2.0: 透過的な分散データベースの使用感

透過的な分散は、PolarDB-X がまもなくリリースする機能です。これにより、アプリケーションはス...

合併と買収の復活によって、インターネットの発展のどのような特徴が明らかになるのでしょうか?

今日のインターネットは、合併や買収が絶えない時代、あるいは寡占の時代とも言えます。競争が激化する中で...

短期間でウェブサイト数を急速に増やす方法の簡単な分析

ロングテールキーワードは、他の最適化方法に比べて競争が少なく、ターゲットがより正確で、コンバージョン...

reprisehosting: 米国西海岸の安価な専用サーバー。「Alipay」に接続されており、月額 26.95 ドルからご利用いただけます。

格安サーバーを専門に扱うreprisehostingは、現在から9月25日まで、米国西海岸のシアトル...

人と会話できる財務管理AIがバンドカンファレンスでデビュー。誰かが1時間半も話していた。

「こんにちは。投資したいお金があります。期待収益は 6 ~ 10 ポイントです。1 年間投資したいと...

UCloud CEO の Ji Xinhua 氏が「トップ 10 の革新的な経済人」賞を受賞

12月26日、「第51回クレジットカード新霊獣夜・中国(杭州)イノベーション経済人表彰式」が盛大に開...

Google アナリティクスの使用に関する 11 のヒントのフォローアップ レポート

「ウェブサイトで活用すべき Google アナリティクスのヒント 11 選」という記事では、目標設定...

「ネットをやめた」羅永浩、生放送室で生放送

「離脱」を発表した翌日の6月13日20時18分、スマートイサンテクノロジーの創始者でDouyinのラ...

JVM の内部: Java 仮想マシンの詳細な説明

[[325305]]この記事では、Java 仮想マシン (JVM) の内部アーキテクチャについて説明...

joes-cloud-$5/kvm/cloudstack/512m メモリ/50g ハードディスク/500g トラフィック

joes-cloud は道徳的誠実さを放棄し、最初の 2 か月間の低価格プロモーションの割引コード ...