Подтвердить что ты не робот

Как сгенерировать поток дампа java из-за ошибки памяти

  • создает java 6 дамп потока в дополнение к дампу кучи (java_pid14941.hprof)

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

    java.lang.OutOfMemoryError: превышен верхний предел GC Сброс кучи в java_pid14941.hprof...

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

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

4b9b3361

Ответ 1

Как создать поток дампа java на ошибка памяти?

Ваш вопрос можно упростить:

  • как сгенерировать дамп потока

и

  • Как поймать ошибку из памяти (не обращайте внимание на naysayer здесь, они пропускают большую картинку, см. мой комментарий).

Так что на самом деле это довольно легко, вы можете сделать это вот так:

  • установить обработчик исключаемых исключений по умолчанию

  • при обнаружении неперехваченного исключения проверьте, есть ли у вас 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

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

-XX:OnOutOfMemoryError="kill -3 pid"

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

Ответ 3

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

jstack -F pid > /var/tmp/<identifier>.dump

Ответ 4

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

И если вы страдаете от OOM, возможно, было бы полезно увидеть, как ситуация эволюционировала по-настоящему.

Ответ 5

На основе принятого ответа я создал класс утилиты. Это можно определить как 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/info/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();
    }
}