1前書き

この記事では、Javaでヒープ・ダンプをキャプチャーするさまざまな方法を紹介します。

  • ヒープダンプは、ある瞬間にJVMのメモリ内にあるすべてのオブジェクトのスナップショットです。これらは、メモリリークの問題のトラブルシューティングやJavaアプリケーションのメモリ使用量の最適化に非常に役立ちます。

  • 通常、ヒープダンプはバイナリ形式のhprofファイルに格納されています** jhatやJVisualVMなどのツールを使用してこれらのファイルを開いて分析できます。また、Eclipseユーザーにとっては、http://www.eclipse.org/mat/[MAT]を使用するのが一般的です。

次のセクションでは、ヒープダンプを生成するための複数のツールとアプローチについて説明し、それらの主な違いについて説明します。


2 JDKツール

JDKには、ヒープダンプをさまざまな方法でキャプチャするためのツールがいくつか付属しています。 ** これらのツールはすべて、JDKホームディレクトリ内の

bin

フォルダの下にあります。したがって、このディレクトリがシステムパスに含まれている限り、コマンドラインから起動できます。

次のセクションでは、ヒープダンプを取得するためにこれらのツールを使用する方法を示します。


2.1. jmap

jmapは実行中のJVMのメモリに関する統計情報を印刷するためのツールです。ローカルまたはリモートプロセスにそれを使用することができます。

  • jmapを使ってヒープダ​​ンプをキャプチャするには、

    dump

    オプションを使う必要があります。

jmap -dump:[live],format=b,file=<file-path> <pid>

そのオプションとともに、いくつかのパラメータを指定する必要があります。


  • live

    :設定されている場合、アクティブな参照を持つオブジェクトのみを印刷します。

ガベージコレクションの準備ができているものは破棄します。このパラメータ
オプションです
**

format = b

:ダンプファイルをバイナリ形式にすることを指定します。もし

設定しない結果は同じです
**

file

:ダンプが書き込まれるファイル


  • pid

    :JavaプロセスのID

例は次のようになります。

jmap -dump:live,format=b,file=/tmp/dump.hprof 12587


jps

コマンドを使用すると、Javaプロセスの

pid

を簡単に取得できることを忘れないでください。

  • jmapは実験的なツールとしてJDKに導入されており、サポートされていないことに注意してください。したがって、場合によっては、代わりに他のツールを使用することをお勧めします。


2.2. jcmd

jcmdは、JVMにコマンド要求を送信することによって機能する、非常に完成度の高いツールです。 Javaプロセスが実行されているのと同じマシンで使用する必要があります。

  • その多くのコマンドのうちの1つは


    _GC.heap

    dump

    _

    ** です。プロセスの

    pid__と出力ファイルのパスを指定するだけで、ヒープダンプを取得できます。

jcmd <pid> GC.heap__dump <file-path>

以前に使用したのと同じパラメータを使用して実行できます。

jcmd 12587 GC.heap__dump/tmp/dump.hprof

jmapと同様に、生成されるダンプはバイナリ形式です。


2.3. JVisualVM

  • JVisualVMは、Javaアプリケーションの監視、トラブルシューティング、プロファイル作成を可能にするグラフィカルユーザーインタフェースを備えたツールです。 GUIはシンプルですが非常に直感的で使いやすいです。

その多くのオプションのうちの1つは私達がヒープダンプを捕獲することを可能にします。 Javaプロセスを右クリックして

“ Heap Dump”

オプションを選択すると、ツールはヒープダンプを作成し、それを新しいタブで開きます。


“基本情報”

セクションに作成されたファイルのパスが見つかります。


3ヒープダンプを自動的に取得する

前のセクションで示したすべてのツールは、特定の時間に手動でヒープダンプを取得することを目的としています。場合によっては、

java.lang.OutOfMemoryError

が発生したときにヒープダンプを取得したいので、エラーの調査に役立ちます。

これらの場合、** Javaは

java.lang.OutOfMemoryError

がスローされたときにヒープダンプを生成する

HeapDumpOnOutOfMemoryError

コマンドラインオプションを提供します。

java -XX:+HeapDumpOnOutOfMemoryError

  • デフォルトでは、ダンプはアプリケーションを実行しているディレクトリの

    java

    pid <pid> .hprof

    ファイルに保存されます。別のファイルまたはディレクトリを指定したい場合は、

    HeapDumpPath__オプションでそれを設定できます。

java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>

このオプションを使用してアプリケーションのメモリが不足すると、ログにヒープダンプを含む作成ファイルが表示されます。

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
Dumping heap to java__pid12587.hprof ...
Exception in thread "main" Heap dump file created[4744371 bytes in 0.029 secs]java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at com.baeldung.heapdump.App.main(App.java:7)

上記の例では、

java

pid12587.hprof__ファイルに書き込まれています。

ご覧のとおり、このオプションは非常に便利であり、

このオプションを指定してアプリケーションを実行してもオーバーヘッドはありません。したがって、特に本番環境では、このオプションを常に使用することを強くお勧めします。

最後に、** このオプションは

HotSpotDiagnostic

MBeanを使用して実行時に指定することもできます。そのためには、JConsoleを使用して

HeapDumpOnOutOfMemoryError

VMオプションを

true

に設定します。

リンク:/uploads/jconsole-setvmoption-1-100×84.png%20100w[]

私達はこのhttps://www.baeldung.com/java-management-extensions[article]にMBeanとJMXに関するより多くの情報を見つけることができます。


4 JMX

この記事で取り上げる最後のアプローチはJMXを使用することです。

前のセクションで簡単に紹介した

HotSpotDiagnostic

MBean

を使用します。 ** このMBeanは2つのパラメータを受け取る

dumpHeap

メソッドを提供します。


  • outputFile

    :ダンプ用のファイルのパス。ファイルは

hprof拡張子
**

live

:trueに設定すると、メモリ内のアクティブなオブジェクトだけをダンプします。

以前にjmapで見たことがある

次のセクションでは、ヒープダンプを取得するためにこのメソッドを呼び出す2つの異なる方法を示します。


4.1.

JConsole



HotSpotDiagnostic

MBeanを使用する最も簡単な方法は、JConsoleなどのJMXクライアントを使用することです。


JConsole

を開いて実行中のJavaプロセスに接続すると、


MBeans

タブに移動して


__

com.sun.management

の下の

HotSpotDiagnostic

が見つかります。


オペレーションでは、前に説明した

dumpHeap__メソッドを見つけることができます。

リンク:/uploads/jconsole-dump-1-100×84.png%20100w[]

図に示すように、

dumpHeap

操作を実行するには、

outputFile

および

live

の各パラメーターを

p0

および

p1

テキストフィールドに追加するだけです。


4.2. プログラムによる方法


HotSpotDiagnostic

MBeanを使用するもう1つの方法は、Javaコードからプログラムで呼び出すことです。

そのためには、まずアプリケーションに登録されているMBeanを取得するために

MBeanServer

インスタンスを取得する必要があります。その後、**

HotSpotDiagnosticMXBean

のインスタンスを取得し、その

dumpHeap

メソッドを呼び出すだけです。

コードで見てみましょう。

public static void dumpHeap(String filePath, boolean live) throws IOException {
    MBeanServer server = ManagementFactory.getPlatformMBeanServer();
    HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy(
      server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
    mxBean.dumpHeap(filePath, live);
}

  • hprofファイルは上書きできないことに注意してください。** したがって、ヒープダンプを出力するアプリケーションを作成するときには、これを考慮する必要があります。そうしないと、例外が発生します。

Exception in thread "main" java.io.IOException: File exists
    at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method)
    at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)


5結論

このチュートリアルでは、Javaでヒープダンプをキャプチャする方法をいくつか示しました。

経験則として、Javaアプリケーションを実行するときは常に

HeapDumpOnOutOfMemoryError

オプションを使用するようにしてください。他の目的のために、私たちがjmapのサポートされていないステータスを覚えている限り、他のツールのどれでも完璧に使うことができます。

いつものように、例の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java[GitHubで利用可能]です。