JVM の内部: Java 仮想マシンの探索

記事ディレクトリ

ブログのマインドマップ

ここに画像の説明を挿入します

1. JVM の概要

Java 仮想マシン ( JVM ) は Java テクノロジのコア コンポーネントであり、Java のクロスプラットフォーム機能の基盤を提供します。JVM は単なる仮想マシンではなく、Java バイトコードのロード、検証、コンパイル、実行を担う完全なランタイム環境です。このセクションでは、JVM の定義、その中核的な役割、およびそのクロスプラットフォーム機能について詳しく説明します。

1.1 定義と中心的な役割

Java 仮想マシンは、デバイスまたはオペレーティング システムに JVM が実装されている限り、Java アプリケーションを任意のデバイスまたはオペレーティング システム上で実行できるようにする仮想コンピュータ インスタンスです。JVM の主なタスクは、.class ファイル (Java バイトコード) をロードして実行することです。これらのバイトコード ファイルは、Java コンパイラによって .java ソース ファイルからコンパイルされます。

JVM のコア機能は次のように要約できます。

  • バイトコードのロード: JVM は、ファイル システムまたはネットワーク リソースから .class ファイルをロードします。

  • バイトコード検証: ロードされたバイトコードが有効で安全であり、JVM の内部データ構造を破損していないことを確認します。

  • ジャストインタイム コンパイル: JVM はジャストインタイム コンパイラ (JIT) を使用してバイトコードをネイティブ マシン コードに変換し、実行速度を向上させることができます。

  • 実行プログラム: JVM は、スレッド、メモリ空間、I/O 操作などのすべてのプログラム リソースを作成および管理し、バイトコードを実行します。

  • 組み込みライブラリの提供: JVM は、Java アプリケーションにコア機能を提供するプリコンパイルされたクラス ライブラリのセットである Java API を提供します。

1.2 JVM のクロスプラットフォーム機能

Java のスローガンは「Write Once, Run Anywhere」です。これは Java のクロスプラットフォーム機能によるもので、この機能の実装は JVM に依存します。

Java プログラムがコンパイルされると、特定のオペレーティング システムに固有のマシン コードではなく、プラットフォームに依存しないバイトコードに変換されます。これは、デバイスに JVM がインストールされている限り、プログラムが最初に作成されたプラットフォームに関係なく、任意の Java アプリケーションを実行できることを意味します。

このアプローチの利点は明らかです。

  • 移植性: Java アプリケーションは、JVM がインストールされている任意のデバイス上で変更を加えることなく実行できます。

  • セキュリティ: Java アプリケーションは仮想マシン上で実行されるため、基盤となるオペレーティング システムから分離されており、アプリケーションに安全な実行環境が提供されます。

  • パフォーマンス: Java アプリケーションは仮想マシン上で実行されますが、ジャストインタイム コンパイル テクノロジーによりネイティブ アプリケーションと同等の速度で実行できます。

  • 統合: Java アプリケーションは、他の言語で記述されたネイティブ アプリケーションと対話できるため、複雑なアプリケーションの統合が容易になります。

要約すると、JVM は Java テクノロジの強固な基盤を提供し、Java を今日最も人気のあるプログラミング言語の 1 つにしています。JVM を深く理解することで、Java がどのように動作するかをより深く理解できるようになり、Java アプリケーションをより効率的に作成および最適化できるようになります。

2. JVM の内部構造の詳細な調査

Java 仮想マシン (JVM) は、Java バイトコードを実行し、Java アプリケーションの実行環境を提供する複雑なシステムです。Java プログラムの実行メカニズムをより深く理解するには、JVM の内部構造とそれがどのように動作するかを詳しく調べる必要があります。

画像-20230915211004027


2.1 クラスローディングの仕組み

Java では、クラスのロード、リンク、および初期化が、JVM が Java プログラムを実行するための基礎となります。これらのプロセスにより、Java クラスが正しく安全に JVM にロードされることが保証されます。

2.1.1 親の委任モデル

親委任モデルは、Java クラス読み込みの中心的なメカニズムです。これにより、Java コア ライブラリのセキュリティが確保され、悪意のあるコードによるコア クラス ライブラリの改ざんが防止されます。

仕組み:
クラスローダーがクラスをロードしようとすると、まず親クラスローダーにタスクを完了するよう要求します。このプロセスは起動クラス ローダーまで再帰的に実行されます。親クラス ローダーがタスクを完了できない場合にのみ、子クラス ローダーはクラス自体のロードを試みます。

// 示例代码:自定义类加载器
public class CustomClassLoader extends ClassLoader {
    
    
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
    
    
        // 委派给父类加载器
        return super.loadClass(name);
    }
}

コードの説明: 上記のコードでは、カスタム クラス ローダーを作成しました。メソッドが呼び出されるとloadClass、まずその親クラス ローダーに委譲されます。

面接での質問 (Alibaba Cloud) :

保護者代表団とは何ですか? 親委任モデルの運用プロセスと利点をいくつか紹介します。

クラスローダーがクラスロード要求を受信した場合、最初にそれをロードするのではなく、その要求を親クラスローダーに委任して実行します。親クラスローダーにまだ親クラスローダーがある場合は、さらに上位に委任します。再帰的に実行され、リクエストは最終的に最上位の起動クラス ローダーに到達します。親クラス ローダーがクラス ロード タスクを完了できれば、正常に戻ります。親クラス ローダーがロード タスクを完了できない場合、子ローダーはそのタスクを試行します。自分のロードに移動、これは親委任モデルです、つまり、息子はそれぞれ働きたくないので、仕事があるたびに父親に任せてそれをやらせます。父親が「私はできない」と言うまでこれは伝説的な親の委任モデルではないでしょうか。

行動プロセス画像-20230915210629324

利点

サンドボックス セキュリティ メカニズム: 自分で作成した String.class クラスはロードされないため、コア API ライブラリが自由に改ざんされることを防ぎ、クラスの繰り返しロードを回避できます: 父親がすでにクラスをロードしている場合、必要はありませ子 ClassLoader がそれを再度ロードするようにします。

2.1.2 OSGIフレームワーク

OSGI (Open Service Gateway Initiative) は、アプリケーションがモジュールを動的にインストール、開始、停止、アンインストールできるようにする Java モジュラー フレームワークです。

仕組み:
OSGI フレームワークは、独自のクラス ローダーを使用してモジュールをロードします。これにより、モジュールが独自のクラス バージョンを持つことができ、クラス バージョンの競合が回避されます。

// 示例代码:OSGI BundleActivator
public class MyActivator implements BundleActivator {
    
    
    public void start(BundleContext context) {
    
    
        System.out.println("Module started");
    }

    public void stop(BundleContext context) {
    
    
        System.out.println("Module stopped");
    }
}

コードの説明: 上記のコードは、モジュールの開始時と停止時にメッセージを出力する単純な OSGI アクティベーターです。

2.1.3 クラスローダーの分類

JVM では、クラス ローダーは 3 つのタイプに分類されます。

  • Bootstrap ClassLoader : などの JVM コア クラス ライブラリのロードを担当しますjava.lang.*

  • Extension ClassLoader : などの Java 拡張ライブラリのロードを担当しますjavax.*

  • Application ClassLoader : アプリケーションのクラスパス、モジュールパスなどのロードを担当します。

// 示例代码:获取类加载器
ClassLoader loader = MyClass.class.getClassLoader();
System.out.println(loader);

コードの説明: 上記のコードは、MyClassクラス ローダーを取得して出力します。


2.2 JVMランタイムデータ領域

JVM が Java プログラムを実行するとき、データを保存するために複数のメモリ領域が使用されます。これらの領域とその目的を理解することは、パフォーマンスを最適化し、問題を診断するために重要です。

2.2.1 プログラムカウンター

プログラム カウンターは、スレッドによって現在実行されているバイトコードのアドレスを保存する小さなメモリ領域です。

仕組み:
JVM がメソッドを実行すると、プログラム カウンターはこのメソッドの最初のバイトコード命令を指します。バイトコード命令が実行されると、プログラム カウンタがインクリメントされます。

// 示例代码:模拟程序计数器
public class ProgramCounterSimulation {
    
    
    public static void main(String[] args) {
    
    
        int counter = 0; // 模拟程序计数器
        method1();
        counter += 3; // 假设method1有3条字节码指令
        method2();
        counter += 2; // 假设method2有2条字节码指令
    }

    public static void method1() {
    
    
        // ...
    }

    public static void method2() {
    
    
        // ...
    }
}

コードの説明: 上記のコードは、プログラム カウンターの動作原理をシミュレートします。メソッドが呼び出されると、バイトコード命令の実行を反映してプログラム カウンタがインクリメントされます。

2.2.2 ローカルメソッドスタック

ローカル メソッド スタックは、Java メソッドのローカル変数、戻りアドレス、その他のデータを格納するメモリ領域です。

仕組み:
JVM がメソッドを呼び出すと、そのメソッドのスタック フレームが作成され、それがローカル メソッド スタックにプッシュされます。このメソッドが戻ると、そのスタック フレームがポップされます。

// 示例代码:模拟本地方法栈
public class LocalMethodStackSimulation {
    
    
    public static void main(String[] args) {
    
    
        method1();
        method2();
    }

    public static void method1() {
    
    
        int localVariable1 = 10; // 存储在本地方法栈中
        // ...
    }

    public static void method2() {
    
    
        String localVariable2 = "Hello"; // 存储在本地方法栈中
        // ...
    }
}

コードの説明: 上記のコードは、ローカル メソッド スタックの動作原理をシミュレートします。各メソッドのローカル変数はローカル メソッド スタックに保存されます。

2.2.3 Java仮想マシンスタック

Java仮想マシンスタックは、Javaメソッドのオペランドスタックやローカル変数テーブルなどのデータを格納するメモリ領域です。

動作原理:
ローカル メソッド スタックと同様に、JVM がメソッドを呼び出すと、このメソッドのスタック フレームが作成され、それが押されます。

Java 仮想マシン スタックを入力します。ただし、ネイティブ メソッド スタックとは異なり、Java 仮想マシン スタックにはオペランド スタックも格納されます。オペランド スタックは、計算プロセス中に中間結果を格納するために使用されるスタックです。

// 示例代码:模拟Java虚拟机栈
public class JVMStackSimulation {
    
    
    public static void main(String[] args) {
    
    
        int result = add(10, 20); // 操作数栈存储10和20,然后存储30(结果)
        System.out.println(result);
    }

    public static int add(int a, int b) {
    
    
        int sum = a + b; // 操作数栈存储a和b的值,然后存储它们的和
        return sum;
    }
}

コードの説明: 上記のコードは、Java 仮想マシン スタックの動作原理をシミュレートします。addメソッドのオペランド スタックには、最初に合計の値が格納され、次にその合計が格納されますab

2.2.4 ヒープ

ヒープは JVM の重要なメモリ領域であり、オブジェクト インスタンスを格納するために使用されます。ガベージ コレクションのパフォーマンスを最適化するために、若い世代と古い世代に分割されます。

仕組み:
新しく作成されたオブジェクトは、最初に若い世代に割り当てられます。時間の経過とともに、生き残ったオブジェクトは若い世代から古い世代に移されます。ほとんどのオブジェクトはすぐにアクセスできなくなるため、ガベージ コレクションは主に若い世代で行われます。

// 示例代码:创建对象
public class HeapSimulation {
    
    
    public static void main(String[] args) {
    
    
        Person person = new Person("Alice", 25); // 对象被分配在堆上
    }
}

class Person {
    
    
    String name;
    int age;

    Person(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }
}

コードの説明: 上記のコードはPersonオブジェクトを作成し、ヒープ上に割り当てます。

2.2.5 メタデータ領域

メタデータ領域は、クラス名、フィールド、メソッドなど、JVM によってロードされるクラスのメタデータを格納するために使用されます。この領域はヒープの一部ではなく、独自のガベージ コレクション戦略を持っています。

仕組み:
JVM がクラスをロードすると、クラスのメタデータがメタデータ領域に保存されます。この領域は固定サイズであり、いっぱいになると、JVM はガベージ コレクションをトリガーして、使用されなくなったクラスのメタデータを再利用します。

// 示例代码:加载类
public class MetadataAreaSimulation {
    
    
    public static void main(String[] args) throws ClassNotFoundException {
    
    
        Class<?> clazz = Class.forName("com.example.MyClass"); // 类的元数据被存储在元数据区
    }
}

コードの説明: 上記のコードはクラスをロードし、そのメタデータ情報をメタデータ領域に保存します。

2.3 JVM メモリ領域のパフォーマンス チューニングの実践

JVM のメモリ領域を理解することは、Java アプリケーションのパフォーマンス チューニングにとって重要です。これらの領域のサイズとパラメーターを調整することで、アプリケーションのパフォーマンスを最適化し、ガベージ コレクションの一時停止時間を短縮し、システムのスループットを向上させることができます。

2.3.1 ヒープメモリのチューニング

実際のケース:
Web アプリケーションで同時実行性が高い状況が頻繁に発生するとしますOutOfMemoryError分析の結果、ヒープ メモリの設定が小さすぎることが原因であることがわかりました。

解決策:
ヒープの最大サイズを増やします。たとえば、最大ヒープ サイズを 2GB に設定します。

java -Xmx2g -jar my-web-app.jar

提案:

  • JVisualVM や JMC などの監視ツールを使用して、ヒープ使用量を定期的にチェックします。
  • アプリケーションに多数の一時オブジェクトがある場合は、若い世代のサイズを増やすことを検討してください。
  • アプリケーションに存続期間の長いオブジェクトが多数ある場合は、古い世代のサイズを増やすことを検討してください。
2.3.2 メタデータ領域のチューニング

実際のケース:
アプリケーションは実行時に多数のクラスを動的に生成し、ロードします。時間が経つと、アプリケーションがOutOfMemoryError: Metaspaceエラーをスローするようになりました。

解決策:
メタデータ領域のサイズを増やします。たとえば、メタデータ領域の最大サイズを 256MB に設定します。

java -XX:MaxMetaspaceSize=256m -jar my-dynamic-app.jar

提案:

  • アプリケーションで多数の動的プロキシまたは CGLIB を使用する場合は、メタデータ領域のサイズを増やすことを検討してください。
  • 頻繁な拡張を避けるために、パラメーターを使用して-XX:MetaspaceSizeメタデータ領域の初期サイズを設定します。
2.3.3 ガベージ コレクション戦略のチューニング

実際のケース:
オンライン取引アプリケーションでは、同時実行性が高い条件下でガベージ コレクションが長時間停止することが多く、その結果、ユーザー エクスペリエンスが低下します。

解決策:
G1 や ZGC などの低遅延ガベージ コレクターに切り替えます。

java -XX:+UseG1GC -jar my-trading-app.jar

提案:

  • アプリケーションのニーズに基づいて、適切なガベージ コレクターを選択してください。たとえば、低レイテンシーのアプリケーションには G1 または ZGC が適しており、高スループットのアプリケーションには Parallel GC がより適している可能性があります。
  • -XX:GCTimeRatioおよびパラメータを使用して、-XX:MaxGCPauseMillisガベージ コレクションの動作を調整します。

3. JVM ガベージ コレクション メカニズム

Java 仮想マシン (JVM) のガベージ コレクション (GC) メカニズムは、Java メモリ管理のコア コンポーネントです。使用されなくなったオブジェクトは自動的にリサイクルされ、メモリが解放されます。このセクションでは、一般的な GC コレクター、ガベージ コレクション アルゴリズム、JVM メモリ パーティションなど、JVM のガベージ コレクション メカニズムについて詳しく説明します。

3.1 一般的な GC コレクター

Java はさまざまな GC コレクターを提供しており、それぞれに固有のアプリケーション シナリオと利点があります。適切なコレクターを選択すると、アプリケーションのパフォーマンスが大幅に向上します。

3.1.1 シリアルコレクター

シリアル コレクターは最も単純な GC コレクターであり、シングル スレッド環境で動作し、ガベージ コレクションの実行中にすべてのアプリケーション スレッドを一時停止します。

利点:

  • シングルスレッドアプリケーションに適しています。
  • スレッド切り替えのオーバーヘッドがないため、通常、シングルスレッド環境では他のコレクタよりも高速です。

短所:

  • 長時間の一時停止が発生する可能性があるため、マルチスレッド アプリケーションには適していません。
// 启用串行收集器
// JVM参数: -XX:+UseSerialGC
3.1.2 CMS (同時マークスイープ) コレクター

CMS コレクターは、アプリケーション スレッドと同時にマーク フェーズとスイープ フェーズを実行する同時コレクターであり、それによって一時停止時間が短縮されます。

利点:

  • 応答時間要件が厳しいアプリケーションに適しています。
  • 一時停止時間を短縮するための同時実行。

短所:

  • CPU 使用率が高くなる可能性があります。
  • 圧縮されないため、メモリの断片化が発生する可能性があります。
// 启用CMS收集器
// JVM参数: -XX:+UseConcMarkSweepGC
3.1.3 パラレルコレクタ

パラレル コレクターはマルチスレッド環境で動作し、ガベージ コレクション中に複数のスレッドを使用します。

利点:

  • マルチスレッドアプリケーションに適しています。
  • マルチコアCPUを最大限に活用できます。

短所:

  • ガベージ コレクション中はすべてのアプリケーション スレッドが一時停止されます。
// 启用并行收集器
// JVM参数: -XX:+UseParallelGC
3.1.4 G1 コレクター

G1 コレクターは、ヒープを複数のリージョンに分割し、ガベージが最も多いリージョンを優先的に収集するリージョン指向のコレクターです。

利点:

  • 応答時間の要件を満たすために一時停止時間を予測できます。
  • マルチコア CPU と大量のメモリを効率的に利用します。

短所:

  • より多くの CPU リソースが必要になる場合があります。
// 启用G1收集器
// JVM参数: -XX:+UseG1GC

面接の質問:
2 種類の GC とは何ですか? マイナー GC とフル GC の違いは何ですか? フル GC はいつトリガーされますか? どのようなアルゴリズムが使用されていますか?

画像-20230915210931693

新世代領域からオブジェクトが消える処理を「マイナーGC」といいます。

旧世代領域からオブジェクトが消える処理を「メジャーGC」といいます。

マイナー GC

YouGen のクリーンアップ、eden のクリーンアップ、および S0\S1 のクリーンアップのプロセス全体はすべて、MinorGC 割り当てによるものです。

障害 (YoungGen 領域のメモリ不足)、minorGC がトリガーされる

メジャー GC

OldGen 領域のメモリ不足によりメジャー GC がトリガーされる

フル GC

フル GC は、若い世代と永続世代を含むヒープ領域全体をクリーンアップします。

フル GC によってトリガーされるシナリオ

1)システム.gc

2) 昇格失敗(世代昇格失敗。例: Eden エリアに残っているオブジェクトが S エリアに昇格したが解放できず、Old エリアに直接昇格しようとしたが解放できず、その後昇格失敗すると FullGC がトリガーされます)

3)CMS の同時モード障害

CMS リサイクル プロセスは主に 4 つのステップに分かれています: 1.CMS 初期マーク 2.CMS 同時マーク 3.CMS リマーク 4.CMS 同時スイープ。2ではgcスレッドとユーザースレッドが同時に実行されるため、ユーザースレッドでも同時にゴミが発生する可能性があり、予約領域に収まらないゴミが多すぎる場合、CMS-Mode-Failureが発生します。 SerialOld シングルスレッドに切り替えてマークスイープを実行します。

4) 新世代昇格の平均サイズが旧世代の残り容量より大きい(新世代から旧世代への昇格が失敗することを避けるため) G1 と CMS を使用すると、Serial+SerialOld として FullGC が発生します。 。ParalOld を使用すると、FullGC は ParallNew + ParallOld として発生します。

3.2 ガベージコレクションアルゴリズム

ガベージ コレクション アルゴリズムは、使用されなくなったオブジェクトを識別してリサイクルする方法を決定します。適切なアルゴリズムを選択すると、ガベージ コレクションの効率が向上します。

3.2.1 レプリ​​ケーションアルゴリズム

コピー アルゴリズムは、一度に 1 つの領域のみを使用して、ヒープを 2 つの等しい領域に分割します。この領域がいっぱいになると、まだ生きているオブジェクトが別の領域にコピーされ、現在の領域がクリアされます。

利点:

  • メモリの断片化はありません。
  • ライブオブジェクトのみを処理する必要があります。

短所:

  • ヒープの実効容量は半分になります。
// 示例代码:复制算法的简化表示
public void copy() {
    
    
    for (Object obj : fromSpace) {
    
    
        if (isAlive(obj)) {
    
    
            toSpace.add(obj);
        }
    }
    fromSpace.clear();
    swap(fromSpace, toSpace);
}

コードの説明: 上記のコードは、レプリケーション アルゴリズムの基本的な動作原理をシミュレートします。まず を走査しfromSpace、ライブオブジェクトを にコピーしtoSpace、次にfromSpace2 つのスペースをクリアして交換します。

3.2.2 マークスイープアルゴリズム

マークスイープ アルゴリズムは、マーク フェーズとクリア フェーズの 2 つのフェーズに分かれています。マーキング フェーズでは、すべてのライブ オブジェクトにマークが付けられ、クリア フェーズでは、マークされていないすべてのオブジェクトがクリアされます。

画像

利点:

  • オブジェクトを移動する必要はありません。
  • 使用されなくなった物体はすべてリサイクルできます。

短所:

  • メモリの断片化を引き起こす可能性があります。
  • パージ フェーズでは、長い停止時間が発生する場合があります。
// 示例代码:标记-清除算法的简化表示
public void markAndSweep() {
    
    
    markAllAliveObjects();
    sweepUnmarkedObjects();
}

コードの説明: 上記のコードは、マークスイープ アルゴリズムの基本的な動作原理をシミュレートします。まず、すべてのライブオブジェクトにマークを付けてから、マークされていないすべてのオブジェクトをクリアします。

3.2.3 マーキング照合アルゴリズム

マーク アンド スイープ アルゴリズムは、マーク アンド スイープ アルゴリズムの変形で、マーク フェーズとスイープ フェーズの間にクリーン フェーズを追加します。デフラグ段階では、残っているすべてのオブジェクトが移動されるため、メモリの断片化が解消されます。

画像

利点:

  • メモリの断片化はありません。
  • 使用されなくなった物体はすべてリサイクルできます。

短所:

  • 移動するオブジェクトが必要なため、時間がかかる可能性があります

一時停止の時間。

// 示例代码:标记-整理算法的简化表示
public void markCompact() {
    
    
    markAllAliveObjects();
    compactAliveObjects();
    sweepUnmarkedObjects();
}

コードの説明: 上記のコードは、マーキング照合アルゴリズムの基本的な動作原理をシミュレートします。最初にすべてのライブ オブジェクトにマークを付け、次にライブ オブジェクトを並べ替え、最後にマークされていないオブジェクトをすべてクリアします。

3.3 JVM メモリ パーティション

JVM はメモリをいくつかの領域に分割し、それぞれに特定の目的とガベージ コレクション戦略があります。

3.3.1 若い世代

若い世代は、Eden エリアと 2 つの Survivor エリアを含むヒープの一部です。新しく作成されたオブジェクトのほとんどは、最初に Eden エリアに割り当てられます。Eden エリアが埋まると、生き残ったオブジェクトは Survivor エリアに移動され、生き残っていないオブジェクトはリサイクルされます。

// 示例代码:创建一个新对象
Object obj = new Object();

コードの説明: 上記のコードは新しいオブジェクトを作成し、最初に Eden 領域に割り当てます。

3.3.2 古い時代

古い世代は、存続期間の長いオブジェクトを格納するために使用されるヒープのもう 1 つの部分です。オブジェクトが Survivor エリアに十分長く存続すると、古い世代に移動されます。

// 示例代码:模拟对象的长时间存活
for (int i = 0; i < 10000; i++) {
    
    
    Object obj = new Object();
    // 使用obj...
}

コードの説明: 上記のコードは、多数のオブジェクトを作成して使用します。これらのオブジェクトは十分に長く存続しているため、古い世代に移動される可能性があります。

3.3.3 メタデータ領域

メタデータ領域は、クラス名、フィールド、メソッドなど、JVM によってロードされるクラスのメタデータ情報を格納するために使用されます。この領域はヒープの一部ではなく、独自のガベージ コレクション戦略を持っています。

// 示例代码:加载一个类
Class<?> clazz = Class.forName("com.example.MyClass");

コードの説明: 上記のコードはクラスをロードし、そのメタデータ情報をメタデータ領域に保存します。

4. JVM ツールとパフォーマンスのチューニング

Java 仮想マシン (JVM) は、開発者がアプリケーションのパフォーマンスを監視、診断、最適化するのに役立つ一連のツールを提供します。これらのツールは、アプリケーションが実行時にどのように動作するかをより深く理解できるようにする深い洞察を提供します。このセクションでは、これらのツールの使用法とパフォーマンス チューニングにおけるそのアプリケーションについて詳しく説明します。


4.1 jmap: Java メモリ マッピング ツール

jmapヒープダンプとメモリマップを生成するツールです。これは、メモリ リークやその他のメモリ関連の問題を診断するのに役立ちます。

4.1.1 ヒープダンプの生成

ヒープ ダンプは、すべてのオブジェクトとその参照を含む JVM メモリのスナップショットです。ヒープ ダンプを分析することで、メモリ リークを特定し、メモリ使用量を最適化できます。

# 生成堆转储
jmap -dump:format=b,file=heapdump.hprof <pid>

コードの説明: 上記のコマンドは、指定されたプロセス ID に応じheapdump.hprofた名前のヒープ ダンプ ファイルを生成します。

4.1.2 ヒープ構成情報の表示

jmapJVM のヒープ構成情報を表示することもできます。これは、ヒープ サイズやその他の関連パラメーターの調整に役立ちます。

# 查看堆配置信息
jmap -heap <pid>

コードの説明: 上記のコマンドは、ヒープ サイズ、使用量、ガベージ コレクション戦略など、指定されたプロセスのヒープ構成情報を表示します。

4.2 jhat: Java ヒープ分析ツール

jhatヒープダンプを解析するためのツールです。hprofファイルを解析し、データをクエリするための Web インターフェイスを提供できます。

4.2.1 jhatを開始する
# 使用jhat分析堆转储
jhat heapdump.hprof

コードの説明: 上記のコマンドは Web サーバーを起動します。デフォルトのポートは 7000 です。ブラウザでアクセスしてhttp://localhost:7000分析結果を表示できます。

4.2.2 クエリオブジェクト

jhatオブジェクトをクエリするための単純な OOQL (オブジェクト指向クエリ言語) を提供します。たとえば、すべてのStringオブジェクトをクエリしたり、特定のオブジェクト参照を検索したりできます。

4.3 jstack: Java スレッド スタック トレース ツール

jstackスレッドスタックトレースを生成するツールです。これは、スレッドのデッドロック、スレッドの枯渇、その他の同時実行の問題を診断するのに役立ちます。

4.3.1 スレッドスタックトレースの生成
# 生成线程堆栈跟踪
jstack <pid>

コードの説明: 上記のコマンドは、指定されたプロセス ID のスレッド スタック トレースを生成します。このトレース情報は、スレッドのステータスとスレッドが実行しているタスクを特定するのに役立ちます。

4.4 jinfo: Java 構成情報ツール

jinfo実行時の JVM 構成を表示および調整できます。これは、JVM パラメータを調整する場合に役立ちます。

4.4.1 JVM フラグの表示
# 查看JVM标志
jinfo -flags <pid>

コードの説明: 上記のコマンドは、ヒープ サイズ、ガベージ コレクション戦略などを含む、指定されたプロセスの JVM フラグを表示します。

4.4.2 JVM フラグの変更
# 修改JVM标志
jinfo -flag +PrintGCDetails <pid>

コードの説明: 上記のコマンドは、指定されたプロセスのフラグを有効にしPrintGCDetails、JVM に詳細なガベージ コレクション ログを出力させます。

4.5 jps: Java プロセス ステータス ツール

jpsJavaのプロセス情報を表示するツールです。ローカル マシン上で実行されているすべての Java プロセスを一覧表示できます。

# 列出所有Java进程
jps -l

コードの説明: 上記のコマンドは、ローカル マシン上で実行されているすべての Java プロセスとそのメイン クラス名を一覧表示します。

おすすめ

転載: blog.csdn.net/weixin_46703995/article/details/132911840