Как создать дамп потока Java на ошибки нехватки памяти - PullRequest
11 голосов
/ 07 мая 2010
  • генерирует ли Java 6 дамп потока в дополнение к дампу кучи (java_pid14941.hprof)

  • это то, что случилось с одним из моих приложений.

    java.lang.OutOfMemoryError: превышен лимит накладных расходов GC Выгрузка кучи в java_pid14941.hprof ...

  • Я нашел ava_pid14941.hprof в рабочем каталоге, но не нашел ни одного файла, содержащего дамп потока. Мне нужно знать, что делали все потоки, когда я получил эту ошибку OutOfMemory.

  • Есть ли опция конфигурации, которая будет генерировать дамп потока в дополнение к дампу кучи при исключении нехватки памяти?

Ответы [ 6 ]

20 голосов
/ 20 мая 2010

Если вы находитесь в среде Linux / Unix, вы можете сделать это:

-XX:OnOutOfMemoryError="kill -3 pid"

Таким образом, вам не нужно, чтобы ваше приложение генерировало периодические дампы потоков, и вы получите моментальный снимок, когда он фактически задохнется.

14 голосов
/ 07 мая 2010

Как создать дамп потока на 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 (на разных ОС).

2 голосов
/ 17 июля 2014

Возможно инициировать дамп потока, когда OnOutOfMemoryError запускается с помощью jstack.Например: -

jstack -F pid > /var/tmp/<identifier>.dump
0 голосов
/ 25 апреля 2018

-XX:OnOutOfMemoryError="kill -3 %p"

К сожалению, аргумент JVM для получения дампа потока не работает. Дочерний процесс не может завершить SIGQUIT для родителя.

Oracle имеет -XX:CrashOnOutOfMemoryError, но это доступно на Java 8.

0 голосов
/ 17 декабря 2014

На основании принятого ответа я создал служебный класс. Этот вы можете определить как 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() {
        /**
         * /2199028/kak-sozdat-damp-potoka-java-na-oshibki-nehvatki-pamyati
         * 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();
    }
}
0 голосов
/ 07 мая 2010

Я не думаю, что в java есть что-то, что могло бы дать вам дамп потока при выходе. Я решаю эту проблему, когда это необходимо, имея cronjob, который делает периодический kill -3 pid. Да, это немного загромождает логи, но занимаемая площадь все еще незначительна.

И если вы страдаете от ООМ, было бы полезно увидеть, как ситуация развивалась в потоке.

...