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

推薦する

世界は将来のリスクへの対応力向上のためデジタル政府構築を強化している

COVID-19パンデミックにより、失業率が急上昇し、地域の多くの国々が大きな圧力にさらされている。...

中小企業は戦略を考える必要はない。最も重要なのは、自ら豆腐を挽くことだ

多くの企業は生き残ることがますます困難になっていると感じています。彼らはもはや消費者を理解しておらず...

ブランドマーケティングの4つの成長ロジック

2016年12月に開催された2017年中央経済工作会議では、中国の経済発展は現在、需要の縮小、供給シ...

YTOはリチウム電池の貨物を虚偽報告したため航空輸送資格を失った

法制晩報によると、今年10月22日に中国南方航空の機内で発生した貨物炎上事件後、中国航空運輸協会(以...

素晴らしい: UBI 6 USD/月 1GB メモリ KVM/10GSSD/1TB トラフィック

今日、QQの友人から素晴らしいニュースを聞きました。UBIがONAPP環境をベースにした素晴らしい製...

K8s コンポーネントの完全な分析: 知っておくべきすべての秘密

Kubernetes をデプロイすると、完全なクラスターが作成されます。 Kubernetes は、...

B2Bプラットフォームを活用した検索マーケティングの実施方法

検索エンジン マーケティングが現在最も注目されているマーケティング手法の 1 つであることは、議論の...

Hostsolutions: 1Gbps 帯域幅の無制限トラフィック サーバーと苦情に強いサーバーを格安で販売

Hostsolutions がプロモーションを開始し、1Gbps の帯域幅と無制限のトラフィックを備...

クラウド コンピューティング 3.0 のパターンとブレークスルー

クラウドコンピューティング技術は、ICT技術の統合であるだけでなく、ICT技術の新しいビジネスモデル...

2021 年に組織が知っておくべき 6 つのクラウド コンピューティングのトレンド

クラウド コンピューティングの普及により、企業のビジネスのやり方は変化しました。この変革は避けられず...

Google の中国ウェブマスター向けチュートリアルにおけるリンク構造の重要性についての簡単な説明

コアヒント: .リンク アーキテクチャは Web サイト計画の重要な部分であり、Web サイトが検索...

マルチアクセス エッジ コンピューティング: IoT とコネクテッド カーの未来

画像ソース: https://pixabay.com/images/id-4343635/テクノロジ...

ウェブサイトのキーワードを最適化するにはどうすればいいですか?

2018年最もホットなプロジェクト:テレマーケティングロボットがあなたの参加を待っています検索エンジ...

北京、杭州などの当局は、毎年数億元の港湾使用料を支払わなければならないため、Soufang.comをブロックした。

現在、北京はLianjiaとWoaiwojiaを代表とする仲介同盟を設立し、Soufun.comと交...