Java 6 はヒープ ダンプに加えてスレッド ダンプを生成しますか (java_pid14941.hprof)
これは、私のアプリケーションの 1 つに起こったことです。
java.lang.OutOfMemoryError: GC オーバーヘッドの制限を超えました ヒープを java_pid14941.hprof にダンプしています ...
作業ディレクトリに ava_pid14941.hprof が見つかりましたが、スレッド ダンプを含むファイルは見つかりませんでした。この OutOfMemory エラーが発生したときに、すべてのスレッドが何をしていたかを知る必要があります。
メモリ不足の例外でヒープ ダンプに加えてスレッド ダンプを生成する構成オプションはありますか?
6 に答える
Linux/Unix 環境にいる場合は、次のようにできます。
-XX:OnOutOfMemoryError="kill -3 %p"
この方法では、アプリケーションに定期的なスレッド ダンプを生成させる必要がなく、実際にチョークしたときにスナップショットを取得できます。
では%p
、PID を渡す必要はありません。ここで説明したように、JVM は正しいプロセス ID を自動的に選択します。
メモリ不足エラーでスレッドダンプJavaを生成する方法は?
あなたの質問は次のように単純化できます。
- スレッド ダンプを生成する方法
と:
- メモリ不足エラーをキャッチする方法 (ここで否定論者に注意を払わないでください。彼らは全体像を見逃しています。私のコメントを参照してください)
したがって、実際には非常に簡単です。次のようにすることができます。
デフォルトのキャッチされない例外ハンドラをインストールする
キャッチされていない例外をキャッチしたら、OutOfMemoryError があるかどうかを確認します
OutOfMemoryError が発生した場合は、自分で完全なスレッド ダンプを生成し、ユーザーに電子メールで送信するように依頼するか、自動的に送信することを申し出てください。
おまけ:1.5でも問題なく動作します:)
Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
public void uncaughtException( final Thread t, final Throwable e ) {
...
}
あなたはこれを調べたいかもしれません:
e.getMessage();
この:
Thread.getAllStackTraces();
私はこれを、何百もの異なる 1.5 および 1.6 JVM (異なる OS 上) で出荷されるアプリで常に行っています。
受け入れられた回答に基づいて、ユーティリティクラスを作成しました。これを Spring Bean として定義すると、拡張ロギングがすべて設定されます。
import java.util.Iterator;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UncaughtExceptionLogger {
private final static Logger logger = LoggerFactory.getLogger(UncaughtExceptionLogger.class);
@PostConstruct
private void init() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(final Thread t, final Throwable e) {
String msg = ExceptionUtils.getRootCauseMessage(e);
logger.error(String.format("Uncaght exception handler captured expcetion '%s'", msg), e);
if (msg.contains("unable to create new native thread")) {
String dump = captureThreadDump();
logger.error(String.format(
"OutOfMemoryError has been captured for threads limit. Thread dump: \n %s", dump), e);
}
if (ExceptionUtils.getRootCause(e) instanceof OutOfMemoryError) {
String dump = captureThreadDump();
logger.error(String.format("OutOfMemoryError has been captured. Thread dump: \n %s", dump), e);
}
}
});
}
public static String captureThreadDump() {
/**
* http://stackoverflow.com/questions/2787976/how-to-generate-thread-
* dump-java-on-out-of-memory-error
* http://henryranch.net/software/capturing-a-thread-dump-in-java/
*/
Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
Iterator<Thread> iterator = allThreads.keySet().iterator();
StringBuffer stringBuffer = new StringBuffer();
while (iterator.hasNext()) {
Thread key = (Thread) iterator.next();
StackTraceElement[] trace = (StackTraceElement[]) allThreads.get(key);
stringBuffer.append(key + "\r\n");
for (int i = 0; i < trace.length; i++) {
stringBuffer.append(" " + trace[i] + "\r\n");
}
stringBuffer.append("");
}
return stringBuffer.toString();
}
}
Java には、終了時のスレッド ダンプを提供するものはないと思います。必要に応じて、定期的な cronjob を使用してこれに取り組みますkill -3 pid
。はい、ログが少し乱雑になりますが、フットプリントはまだ無視できます.
また、OOM に苦しんでいる場合は、スレッドごとに状況がどのように変化したかを確認することをお勧めします。