如何在内存不足错误时生成线程转储 java

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2787976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:49:59  来源:igfitidea点击:

how to generate thread dump java on out of memory error

javacrash-dumpsjvm-crash

提问by Jigar

  • does java 6 generate thread dump in addition to heap dump (java_pid14941.hprof)

  • this is what happened to one of my applications.

    java.lang.OutOfMemoryError: GC overhead limit exceeded Dumping heap to java_pid14941.hprof ...

  • I did find ava_pid14941.hprof in working directory, but didn't find any file which contains thread dump. I need to know what all the threads were doing when I got this OutOfMemory error.

  • Is there any configuration option which will generate thread dump in addition to heap dump on out of memory exception?

  • 除了堆转储(java_pid14941.hprof)之外,java 6 是否还生成线程转储

  • 这就是我的一个应用程序发生的情况。

    java.lang.OutOfMemoryError: GC 开销限制超出 Dumping heap to java_pid14941.hprof ...

  • 我确实在工作目录中找到了 ava_pid14941.hprof,但没有找到任何包含线程转储的文件。当我收到 OutOfMemory 错误时,我需要知道所有线程在做什么。

  • 除了内存不足异常的堆转储之外,是否有任何配置选项会生成线程转储?

回答by Jim Bethancourt

If you're in a Linux/Unix environment you can do this:

如果你在 Linux/Unix 环境中,你可以这样做:

-XX:OnOutOfMemoryError="kill -3 pid"

This way you don't have to have your application generate periodic thread dumps and you'll get a snapshot when it actually chokes.

这样您就不必让您的应用程序生成定期的线程转储,并且您将在它实际阻塞时获得快照。

回答by SyntaxT3rr0r

How to generate thread dump java on out of memory error?

如何在内存不足错误时生成线程转储 java?

Your question can be simplified into:

你的问题可以简化为:

  • how to generate a thread dump
  • 如何生成线程转储

and:

和:

  • how to catch an out of memory error (don't pay attention to naysayer here, they're missing the bigger picture, see my comment)
  • 如何捕捉内存不足错误(不要在这里注意反对者,他们错过了更大的图景,请参阅我的评论)

So it's actually quite easy, you could do it like this:

所以它实际上很容易,你可以这样做:

  • install a default uncaught exception handler

  • upon catching an uncaught exception, check if you have an OutOfMemoryError

  • if you have an OutOfMemoryError, generate yourself a full thread dump and either ask the user to send it to you by email or offer to send it automatically

  • 安装默认的未捕获异常处理程序

  • 捕获未捕获的异常后,检查您是否有 OutOfMemoryError

  • 如果您有 OutOfMemoryError,请为自己生成一个完整的线程转储,然后要求用户通过电子邮件将其发送给您,或者提供自动发送

Bonus: it works fine on 1.5 too :)

奖励:它在 1.5 上也能正常工作:)

 Thread.setDefaultUncaughtExceptionHandler( new Thread.UncaughtExceptionHandler() {
     public void uncaughtException( final Thread t, final Throwable e ) {
         ...
     }

You may want to look into this:

你可能想看看这个:

 e.getMessage();

and this:

还有这个:

Thread.getAllStackTraces();

I'm doing this all the time in an app that is shipped on hundreds of different 1.5 and 1.6 JVM (on different OSes).

我一直在一个应用程序中这样做,该应用程序在数百个不同的 1.5 和 1.6 JVM(在不同的操作系统上)上提供。

回答by gilesw

It's possible to trigger a thread dump when OnOutOfMemoryError is triggered using jstack. e.g:-

当使用 jstack 触发 OnOutOfMemoryError 时,可以触发线程转储。例如:-

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

回答by snowindy

Based on the accepted answer I created utility class. This one you can define as a Spring bean and you're all set with extended logging.

根据接受的答案,我创建了实用程序类。您可以将这个定义为 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();
    }
}

回答by Himadri Mandal

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

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

The JVM argument to take thread dump sadly don't work. Child process cannot end SIGQUIT to parent.

可悲的是,JVM 参数进行线程转储不起作用。子进程不能结束对父进程的 SIGQUIT。

Oracle has -XX:CrashOnOutOfMemoryErrorbut this is available on Java 8.

Oracle 有,-XX:CrashOnOutOfMemoryError但这在 Java 8 上可用。

回答by mindas

I don't think there is anything in java that would provide you with on-exit thread dumps. I tackle this when necessary by having a cronjob that does periodic kill -3 pid. Yes, it does clutter the logs a bit, but the footprint is still negligible.

我认为 Java 中没有任何东西可以为您提供退出时的线程转储。必要时,我会通过定期执行 cronjob 来解决此问题kill -3 pid。是的,它确实使日志有点混乱,但足迹仍然可以忽略不计。

And if you are suffering from OOM, it might be be beneficial to see how the situation evolved thread-wise.

如果您正遭受 OOM 的困扰,那么看看情况如何逐线演变可能会有所帮助。