как создать дамп потока java на ошибке из памяти
создает ли java 6 дамп потока в дополнение к дампу кучи (java_pid14941.hprof по)
-
это то, что случилось с одним из моих приложений.
java.ленг.OutOfMemoryError: превышен предел накладных расходов ГК Сброс кучи в java_pid14941.hprof по ...
Я нашел ava_pid14941.hprof в рабочем каталоге, но не нашел файла, который содержит дамп потока. Мне нужно знать, что делали все нити, когда я получил эту ошибку OutOfMemory.
есть ли опция конфигурации, которая будет генерировать дамп потока в дополнение к дампу кучи на исключении из памяти?
6 ответов
как создать дамп потока 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 (на разных ОС).
Если вы находитесь в среде Linux/Unix вы можете сделать это:
-XX:OnOutOfMemoryError="kill -3 pid"
таким образом, вам не нужно, чтобы ваше приложение генерировало периодические дампы потоков, и вы получите снимок, когда он фактически задохнется.
можно вызвать дамп потока, когда OnOutOfMemoryError запускается с помощью jstack. е.г:-
jstack -F pid > /var/tmp/<identifier>.dump
Я не думаю, что в java есть что-то, что предоставит вам дампы потоков при выходе. Я решаю это, когда это необходимо, имея cronjob, который делает периодические kill -3 pid
. Да, он немного загромождает бревна, но след все еще незначителен.
и если вы страдаете от OOM, было бы полезно посмотреть, как ситуация развивалась по потоку.
на основе принятого ответа, я создал вспомогательный класс. Этот вы можете определить как 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();
}
}
-XX:OnOutOfMemoryError="kill -3 %p"
аргумент JVM для взятия дампа потока, к сожалению, не работает. Дочерний процесс не может завершить SIGQUIT к родительскому.
Oracle имеет -XX:CrashOnOutOfMemoryError
но это доступно на Java 8.