web-dev-qa-db-ja.com

Javaメモリ不足の自動ヒープダンプファイル名

私はいくつかのJavaプロセスがあり、OOMエラーが発生したときに作成されたヒープダンプを管理しようとしています。

  • 元のプロセスに基づいて、ヒープダンプに異なる名前を付けます
  • 古いヒープダンプを削除して、ディスク領域を保持する

でOOMにヒープをダンプする場合

 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

jVMは、指定された/ tmpフォルダーに次の名前Java_pidXXXX.hprofのファイルを作成します(XXXXはプロセスのPIDです)。とにかく、PIDとDATEを使用してファイル名を作成する別の形式を指定する必要はありますか? 1時間グーグルで調べた後、myPrefix _ $、{pid}、 'date' .. etcを試しました。動作するのは2つだけです

  1. ファイル名を指定しないで、Java_pidXXXX.hprofを取得します
  2. 静的ファイル名を指定します\ tmp\OOM.hprof。

\ tmpフォルダーが存在しない場合は作成されず、ヒープダンプも作成されません。

使用できる1つのアイデアは、OOMエラーにコマンドを追加することです

-XX:OnOutOfMemoryError="doSomething.sh %p"

しかし、「doSomething.sh」を展開する必要があるため、それを回避しようとしていました

17
Dan M

コマンドラインの_-XX:HeapDumpPath_は、既に発見したものよりも柔軟性がありません。つまり、次のいずれかを実行できます。

  • ディレクトリ名を設定すると、デフォルト名_Java_pidXXX.hprof_がそのディレクトリに作成されます。
  • ファイル名を設定すると、そのファイルがそのまま使用されます。

HotSpotソースの関連コードは heapDumper.cpp です。それを読んで、それは与えられたパス内の「マジックシーケンス」を探しません:

  • 指定されたパスがディレクトリかどうかを確認します。その場合、それを接頭辞として使用し、ファイル区切り文字を追加し、制御できない文字列形式を使用してハードコードされた部分で構成されるデフォルトのファイル名を使用します。
  • ディレクトリでない場合は、そのまま使用します。
  • このJVMのライフタイムの最初のダンプではない場合、シーケンス番号も追加されます。

それでおしまい。それがディレクトリであるかどうかを判断する以外のパスの解析はありません。

追加できる唯一の柔軟性は、コマンドラインで名前を作成するときにシェルの機能を使用することです。そのため、_name_`date`.ext_のようなものを使用するいくつかの例をWebで見ることができます。これは、_`date`_を現在の日付once。つまり、ファイル名には、シェルがコマンドを処理してJVMを起動したときの日付/時刻が常に含まれます-ダンプが作成された日付/時刻ではありません。それで十分であれば、それを使用できます。現在、name_$(date).ext構文を使用する方がより適切であると考えられていることに注意してください。

古いファイルを削除するために日付のみが必要な場合は、ファイルの最終変更時刻に基づいて削除できます(Unix/Linuxユーティリティfindが役立ちます)。名前に日付を含める必要はありません。

$(date)(または_`date`_)トリックは、PIDに役立ちません。 _$$_を使用する場合、シェルは現在のPIDを置き換えることもできますが、それはコマンドラインを処理するシェルのPIDであり、JVMプロセス自体ではありません。ただし、Shell execコマンドを使用してJavaアプリケーションを起動した場合、元のシェルと同じプロセスIDを受け取るため、実際に_$$_を使用できますただし、execの後はスクリプトから実行されないことに注意してください。

したがって、@ apanginが彼の答えで提案したファイル名の動的な変更を試してみてください。ただし、OOMが実際に発生する前にファイル名を設定する必要があるため、ダンプ自体の時間を特定することはおそらく少し難しいことに注意してください。

9
RealSkeptic

HeapDumpPathは管理可能なVMオプションです。これは、JMXを使用してランタイムで必要なものに設定できることを意味します。

    String pid = ManagementFactory.getRuntimeMXBean().getName();
    pid = pid.substring(0, pid.indexOf('@'));
    String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    String fileName = "/tmp/heap_" + pid + "_" + date + ".dump";

    HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
            ManagementFactory.getPlatformMBeanServer(),
            "com.Sun.management:type=HotSpotDiagnostic",
            HotSpotDiagnosticMXBean.class);
    bean.setVMOption("HeapDumpOnOutOfMemoryError", "true");
    bean.setVMOption("HeapDumpPath", fileName);
8
apangin